工具类NetUtil
package com.example.loadimage;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.util.Log;
import android.util.LruCache;
import android.widget.ImageView;
import com.google.gson.Gson;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.security.MessageDigest;
import java.util.HashMap;
import java.util.LinkedHashMap;
public class NetUtil {
//单例
private static NetUtil instance;
//图片内存缓存
private LruCache<String, Bitmap> cache;
//HashMap<String, Bitmap> m;//无序的
//LinkedHashMap<String, Bitmap>m;//有序的
private File saveDir;
//私有构造方法
private NetUtil(Context context) {
int size = (int)(Runtime.getRuntime().freeMemory() * 0.3);
cache = new LruCache<>(size);
//图片文件缓存目录
saveDir = new File(context.getCacheDir(), "img_cache");
//不存在,创建
if(!saveDir.exists()) {
saveDir.mkdirs();
}
}
//提供方法,获取对象
public static NetUtil getInstance(Context context) {
if(instance == null) {
instance = new NetUtil(context);
}
return instance;
}
/*public interface ImageCallbak2 {
void onStartLoadImage(String url, ImageView imageView);
void onLoadImageSuccess(String url, Bitmap bitmap, ImageView imageView);
}
public void displayBitmap3(final String urlStr, final ImageView imageView) {
displayBitmap(urlStr, imageView, new ImageCallbak2() {
@Override
public void onStartLoadImage(String url, ImageView imageView) {
imageView.setTag(url);
}
@Override
public void onLoadImageSuccess(String url, Bitmap bitmap, ImageView imageView) {
if(imageView.getTag().equals(url)) {
imageView.setImageBitmap(bitmap);
} else {
Log.i("TEST", "错乱");
}
}
});
}
public void displayBitmap(final String url, final ImageView imageView, final ImageCallbak2 callbak2) {
callbak2.onStartLoadImage(url, imageView);
new AsyncTask<String, Void, Bitmap>(){
@Override
protected Bitmap doInBackground(String... strings) {
return getBitmap(strings[0]);
}
@Override
protected void onPostExecute(Bitmap bitmap) {
callbak2.onLoadImageSuccess(url, bitmap, imageView);
}
};
}*/
//1 定义接口:合同
public interface ImageCallback {
void loadImageSuccess(String url, Bitmap bitmap);
}
//接口回调
public void getBitmap(final String urlStr, final ImageCallback callback) {
new AsyncTask<String, Void, Bitmap>(){
@Override
protected Bitmap doInBackground(String... strings) {
return getBitmap(strings[0]);
}
@Override
protected void onPostExecute(Bitmap bitmap) {
callback.loadImageSuccess(urlStr, bitmap);
}
}.execute(urlStr);
}
//展示图片,没有错乱
public void displayBitmap2(final String urlStr, final ImageView imageView) {
//绑定url到imageview
imageView.setTag(urlStr);
new AsyncTask<String, Void, Bitmap>(){
@Override
protected Bitmap doInBackground(String... strings) {
return getBitmap(strings[0]);
}
@Override
protected void onPostExecute(Bitmap bitmap) {
if(imageView.getTag().equals(urlStr)) {
imageView.setImageBitmap(bitmap);
}else {
Log.i("TEST", "错乱");
}
}
}.execute(urlStr);
}
//请求一张图片,展示给ImageView
//异步任务
public void displayBitmap(String urlStr, final ImageView imageView) {
new AsyncTask<String, Void, Bitmap>(){
@Override
protected Bitmap doInBackground(String... strings) {
return getBitmap(strings[0]);
}
@Override
protected void onPostExecute(Bitmap bitmap) {
imageView.setImageBitmap(bitmap);
}
}.execute(urlStr);
}
//获取图片
public Bitmap getBitmap(String urlStr) {
Bitmap result = null;
//从内存中要
result = cache.get(url2Key(urlStr));
//内存命中
if(result != null) {
Log.i("TEST", "内存中加载图片: " + urlStr);
return result;
}
//从磁盘中要
result = getBitmapForFile(urlStr);
//文件命中
if(result != null) {
Log.i("TEST", "磁盘中加载图片: " + urlStr);
//先存到内存缓存
cache.put(url2Key(urlStr), result);
return result;
}
//从网络中请
Log.i("TEST", "网络中加载图片: " + urlStr);
result = getBitmapForNetwork(urlStr);
//写文件
saveBitmap2File(urlStr, result);
//存到内存缓存
cache.put(url2Key(urlStr), result);
return result;
}
//将url转换成key
//url 做key: 太长;如果作为文件名,不允许/ ?
private String url2Key(String url) {
//MD5 摘要方法
//MessageDigest
return String.valueOf(url.hashCode());
}
//将图片存到文件
private void saveBitmap2File(String urlStr, Bitmap bitmap) {
//格式: png jpeg(jpg)
//质量: 0 100
FileOutputStream fos = null;
try {
fos = new FileOutputStream(new File(saveDir,url2Key(urlStr)));
//图片质量压缩, 并输出到输出流
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos);
} catch (FileNotFoundException e) {
e.printStackTrace();
}finally {
if(fos != null) {
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
//从文件读取图片
private Bitmap getBitmapForFile(String urlStr) {///
//解码文件为bitmap图片
return BitmapFactory.decodeFile(new File(saveDir, url2Key(urlStr)).getAbsolutePath());
}
//执行一个网络请求,返回一个Bitmap
//这一步做:请求图片
private Bitmap getBitmapForNetwork(String urlStr) {
Bitmap result = null;
try {
URL url = new URL(urlStr);
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setRequestMethod("GET");
urlConnection.setConnectTimeout(5000);
urlConnection.setReadTimeout(5000);
int responseCode = urlConnection.getResponseCode();
if(responseCode == 200) {
result = BitmapFactory.decodeStream(urlConnection.getInputStream());
}
} catch (java.io.IOException e) {
e.printStackTrace();
}
return result;
}
///普通get请求
public interface Callbak<T>{
void onSuccess(T t);
}
///执行一个网络请求,通过回调返回结果
public void getRequest(final String urlStr, final Class clazz, final Callbak callbak) {
new AsyncTask<String, Void, Object>(){
@Override
protected Object doInBackground(String... strings) {
return getRequest(urlStr, clazz);
}
@Override
protected void onPostExecute(Object o) {
callbak.onSuccess(o);
}
}.execute(urlStr);
}
//执行一个网络请求,返回bean
public <T> T getRequest(String urlStr, Class clazz) {
return (T) new Gson().fromJson(getRequest(urlStr), clazz);
}
//执行一个网络请求,返回String结果
public String getRequest(String urlStr) {
String result = "";
try {
URL url = new URL(urlStr);
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setRequestMethod("GET");
urlConnection.setConnectTimeout(5000);
urlConnection.setReadTimeout(5000);
int responseCode = urlConnection.getResponseCode();
if(responseCode == 200) {
result = stream2String(urlConnection.getInputStream());
}
} catch (java.io.IOException e) {
e.printStackTrace();
}
return result;
}
private String stream2String(InputStream is) throws IOException {
StringBuilder sb = new StringBuilder();
BufferedReader br = new BufferedReader(new InputStreamReader(is));
for (String tmp = br.readLine(); tmp != null; tmp = br.readLine()) {
sb.append(tmp);
}
return sb.toString();
}
}
主线程MainActivity
单一性只做操作
package com.example.loadimage;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.ListView;
public class MainActivity extends AppCompatActivity {
private ListView news;
private MyBaseAdafter mAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
news = findViewById(R.id.news);
mAdapter = new MyBaseAdafter(this);
news.setAdapter(mAdapter);
findViewById(R.id.left).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//加载数据
NetUtil.getInstance(MainActivity.this).getRequest("http://api.expoon.com/AppNews/getNewsList/type/1/p/1", Bean.class, new NetUtil.Callbak<Bean>() {
@Override
public void onSuccess(Bean o) {
mAdapter.setListData(o.getData());
}
});
}
});
}
}
适配器 MyBaseAdafter
package com.example.loadimage;
import android.content.Context;
import android.graphics.Bitmap;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.List;
public class MyBaseAdafter extends BaseAdapter {
private Context context;
private List<Bean.DataBean>mlist;
public MyBaseAdafter(Context context) {
this.context = context;
mlist = new ArrayList<>();
}
public void setListData(List<Bean.DataBean> list){
this.mlist = list;
notifyDataSetChanged();
}
@Override
public int getCount() {
return mlist.size();
}
@Override
public Bean.DataBean getItem(int position) {
return mlist.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
final ViewHoder viewHoder;
if(convertView==null){
convertView = LayoutInflater.from(context).inflate(R.layout.item,parent,false);
viewHoder = new ViewHoder();
viewHoder.textView1 = convertView.findViewById(R.id.textview1);
viewHoder.textView2 = convertView.findViewById(R.id.textview2);
viewHoder.imageView = convertView.findViewById(R.id.imageview);
convertView.setTag(viewHoder);
}else{
viewHoder = (ViewHoder) convertView.getTag();
}
viewHoder.textView1.setText(mlist.get(position).getNews_title());
viewHoder.textView2.setText(mlist.get(position).getNews_summary());
//加载图片
//错乱问题
//NetUtil.getInstance().displayBitmap(getItem(position).getPic_url(), viewHoder.imageView);
//NetUtil.getInstance().displayBitmap2(getItem(position).getPic_url(), viewHoder.imageView);
viewHoder.imageView.setTag(getItem(position).getPic_url());
NetUtil.getInstance(context).getBitmap(getItem(position).getPic_url(), new NetUtil.ImageCallback() {
@Override
public void loadImageSuccess(String url, Bitmap bitmap) {
if(viewHoder.imageView.getTag().equals(url)) {
viewHoder.imageView.setImageBitmap(bitmap);
}else {
}
}
});
return convertView;
}
class ViewHoder{
private TextView textView1,textView2;
private ImageView imageView;
}
}
BitmapUtil
package com.example.loadimage;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
public class BitmapUtil {
public Bitmap scaleBitmap(int width, int height) {
Bitmap result = null;
return result;
}
}