上一期介绍了AsyncTask这个异步类的用法,这次使用到了图片加载类ImageLoader。
先上代码:
package com.sdf.imoocnews;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.os.Handler;
import android.os.Message;
import android.support.v4.util.LruCache;
import android.widget.ImageView;
public class ImageLoader {
private ImageView mImageView;
private String mUrl;
// 创建缓存cache,以key value的形式保存
private LruCache<String, Bitmap> mCaches;
public ImageLoader() {
// 得到最大的内存
int maxSize = (int) Runtime.getRuntime().maxMemory();
// 获得所需的图片加载的内存
int cacheSize = maxSize / 4;
mCaches = new LruCache<String, Bitmap>(cacheSize) {
// 必须重写sizeof()方法,返回保存的对象内存的大小,否则默认返回个数
// 每次加入缓存的时候,调用sizeof()方法,所以要明确bitmap的大小
protected int sizeOf(String key, Bitmap value) {
// 在每次加入的时候调用
return value.getByteCount();
};
};
}
// 增加到缓存
public void addBitmapToCache(String url, Bitmap bitmap) {
if (getBitmapFromCache(url) == null) {
mCaches.put(url, bitmap);
}
}
// 从缓存中获得数据,通过url返回bitmap
public Bitmap getBitmapFromCache(String url) {
return mCaches.get(url);
}
private Handler mHandler = new Handler() {
public void handleMessage(android.os.Message msg) {
if (mImageView.getTag().equals(mUrl)) {
// 通过tag对应相应的图片,防止listView滑动过程中出现图片的错位与错乱
mImageView.setImageBitmap((Bitmap) msg.obj);
}
};
};
public void showImageByThread(ImageView imageView, final String url) {
mImageView = imageView;
mUrl = url;
new Thread() {
public void run() {
super.run();
Bitmap bitmap = getBitmapFromUrl(url);
Message message = Message.obtain();
message.obj = bitmap;
mHandler.sendMessage(message);
};
}.start();
}
public void showImageByAsyncTask(ImageView imageView, String url) {
Bitmap bitmap = getBitmapFromCache(url);
if (bitmap == null) {
new NewsAsyncTask(imageView, url).execute(url);
} else {
imageView.setImageBitmap(bitmap);
}
}
private class NewsAsyncTask extends AsyncTask<String, Void, Bitmap> {
private ImageView mImageView;
private String mUrl;
public NewsAsyncTask(ImageView imageView, String url) {
mImageView = imageView;
mUrl = url;
}
@Override
protected Bitmap doInBackground(String... params) {
// TODO Auto-generated method stub
String url = params[0];
// 从网络获取图片
Bitmap bitmap = getBitmapFromUrl(url);
if (bitmap != null) {
addBitmapToCache(url, bitmap);
}
return bitmap;
}
@Override
protected void onPostExecute(Bitmap bitmap) {
// TODO Auto-generated method stub
super.onPostExecute(bitmap);
if (mImageView.getTag().equals(mUrl)) {
mImageView.setImageBitmap(bitmap);
}
}
}
public Bitmap getBitmapFromUrl(String urlString) {
Bitmap bitmap;
InputStream is = null;
try {
URL url = new URL(urlString);
HttpURLConnection connection = (HttpURLConnection) url
.openConnection();
is = new BufferedInputStream(connection.getInputStream());
bitmap = BitmapFactory.decodeStream(is);
connection.disconnect();
return bitmap;
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
try {
is.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return null;
}
}
这里首先写NewsAsyncTask这个类然后继承AsyncTask这个类,在doInBackground方法里依然是最费时的网络通信操作,这里我们还是用到了LruCache这个类,用来进行缓存的。这样listView加载的图片就能保存在本地,不用每次打开都重新加载,浪费手机流量。LruCache是以key-value的形式缓存的,可以借鉴下sharedpreference。
使用起来也很简单,先初始化,然后就是要覆写sizeof()方法,因为这个方法默认的是返回的对象的个数,而我们需要的是每个对象的内存的大小。只要写上return value.getByteCount()就行了。
最简单的增加缓存与得到缓存内容:
// 增加到缓存
public void addBitmapToCache(String url, Bitmap bitmap) {
if (getBitmapFromCache(url) == null) {
mCaches.put(url, bitmap);
}
}
// 从缓存中获得数据,通过url返回bitmap
public Bitmap getBitmapFromCache(String url) {
return mCaches.get(url);
}
这里使用了两个方法来加载图片,一个是Thread,另一个就是AsyncTask。可以看出各自的优缺点。
应该都可以看懂。。。我学LruCache也只到这个地步,很浅。。代码到这里就能