模拟android中的消息机制实现图片的异步加载和动态显示
001 | package cn.jd3g.utils; |
003 | import java.lang.ref.SoftReference; |
004 | import java.util.HashMap; |
005 | import java.util.LinkedHashMap; |
006 | import java.util.Map.Entry; |
008 | import android.graphics.Bitmap; |
009 | import android.os.Handler; |
010 | import android.util.Log; |
011 | import android.widget.ImageView; |
019 | public final
class AsynImageLoader { |
021 | private
LoaderThread thread; |
022 | private
HashMap<String, SoftReference<Bitmap>> imageCache; |
023 | private
Handler handler; |
025 | public
AsynImageLoader(Handler handler) { |
026 | imageCache =
new HashMap<String, SoftReference<Bitmap>>(); |
027 | this .handler = handler; |
031 | * 加载图片前显示到指定的ImageView中,图片的url保存在视图对象的Tag中 |
035 | * @param defaultBitmap |
036 | * 加载需要显示的提示正在加载的默认图片对象 |
038 | public
void loadBitmap(ImageView imageView, Bitmap defaultBitmap) { |
040 | String url = (String) imageView.getTag(); |
041 | if
(imageCache.containsKey(url)) { |
042 | SoftReference<Bitmap> softReference = imageCache.get(url); |
043 | Bitmap bitmap = softReference.get(); |
044 | if
(bitmap != null ) { |
045 | imageView.setImageBitmap(bitmap); |
048 | Log.e( "TAG" ,
"cache bitmap is null" ); |
049 | imageCache.remove(url); |
052 | imageView.setImageBitmap(defaultBitmap); |
053 | if
(thread == null ) { |
054 | thread =
new LoaderThread(imageView, url); |
057 | thread.load(imageView, url); |
063 | * 释放缓存中所有的Bitmap对象,并将缓存清空 |
065 | public
void releaseBitmapCache() { |
066 | if
(imageCache != null ) { |
067 | for
(Entry<String, SoftReference<Bitmap>> entry : imageCache.entrySet()) { |
068 | Bitmap bitmap = entry.getValue().get(); |
069 | if
(bitmap != null ) { |
080 | private
class LoaderThread extends
Thread { |
082 | LinkedHashMap<String, ImageView> mTaskMap; |
083 | private
boolean mIsWait; |
085 | public
LoaderThread(ImageView imageView, String url) { |
086 | mTaskMap =
new LinkedHashMap<String, ImageView>(); |
087 | mTaskMap.put(url, imageView); |
095 | public
void load(ImageView imageView, String url) { |
096 | mTaskMap.remove(imageView); |
097 | mTaskMap.put(url, imageView); |
099 | synchronized
( this ) { |
107 | while
(mTaskMap.size() > 0 ) { |
109 | final
String url = mTaskMap.keySet().iterator().next(); |
110 | final
ImageView imageView = mTaskMap.remove(url); |
111 | if
(imageView.getTag() == url) { |
112 | final
Bitmap bitmap = MyConnection.getBitmapByUrl(url); |
115 | }
catch (InterruptedException e1) { |
116 | e1.printStackTrace(); |
119 | imageCache.put(url,
new SoftReference<Bitmap>(bitmap)); |
120 | if
(url == imageView.getTag()) { |
121 | handler.post( new
Runnable() { |
124 | imageView.setImageBitmap(bitmap); |
129 | if
(mTaskMap.isEmpty()) { |
132 | synchronized
( this ) { |
135 | }
catch (InterruptedException e) { |
01 | private class
ProductListAdapter extends
BaseAdapter { |
03 | private
AsynImageLoader mImageAsynLoader; |
05 | public
ProductListAdapter() { |
06 | mImageAsynLoader =
new AsynImageLoader(mHandler); |
10 | public
int getCount() { |
11 | int
size = Math.min(mLastItemViewIndex + 1 , mDataList.size()); |
12 | mLastItemViewIndex = size -
1 ; |
17 | public
Object getItem( int
position) { |
18 | return
mDataList.get(position); |
22 | public
long getItemId( int
position) { |
27 | public
View getView( int
position, View convertView, ViewGroup parent) { |
28 | if
(convertView == null ) { |
29 | convertView = getLayoutInflater().inflate(R.layout.product_list_item, |
32 | ImageView imageView = (ImageView) convertView |
33 | .findViewById(R.id.iv_item_product_image); |
34 | Map<String, String> map = mDataList.get(position); |
36 | imageView.setTag(map.get( "product_pic_address" )); |
37 | mImageAsynLoader.loadBitmap(imageView, mDefautBitmap); |
****************************************************************************************************************************************************************************
Android应用中,从远程获取图片算是经常要用的一个功能,而图片资源往往会消耗比较大的流量,而且如果加载在图片比较多的View中,如ListView GridView WebView中,加载速度会比较缓慢。Android中图片加载速度很慢的话,程序很容易就挂掉,等待的用户用户同样会等到崩溃。
我们一般的处理方法是:
异步下载
本地缓存
-----------------------------------------------------------
先说异步下载

如一个ListView的异步下载
它的Adapter是
- public class InsuranceItemAdapter extends BaseAdapter{
- private ArrayList<data> mList;
- private Context mContext;
-
- private AsyncImageLoader imageLoader = new AsyncImageLoader();
-
- private Map<Integer, View> viewMap = new HashMap<Integer, View>();
-
- public InsuranceItemAdapter(Context context, ArrayList<data> ins) {
- mContext = context;
- mList= ins;
- }
-
- public InsuranceItemAdapter(Context context, ArrayList<data> ins,
- Handler handler) {
- mContext = context;
- mList= ins;
- }
-
- public void setInsurance(ArrayList<data> ins) {
- mList= ins;
- }
-
-
-
- public int getCount() {
- return mList.size();
- }
-
- public Object getItem(int position) {
- try {
- return mList.get(position);
- } catch (Exception ex) {
- return null;
- }
- }
-
- public long getItemId(int position) {
- return position;
- }
-
-
- private View newView() {
- ItemView view = new ItemView(mContext);
- return view;
- }
-
-
-
- public View getView(int position, View convertView, ViewGroup parent) {
-
- ViewHolder holder = null;
- View view;
-
- if (viewMap.get(position) == null) {
- view = newView();
- holder = new ViewHolder();
- holder.mTitle = (TextView)view.findViewById(R.id.ins_title);
- holder.mTime = (TextView)view.findViewById(R.id.ins_time);
- holder.mType = (TextView)view.findViewById(R.id.ins_from);
- holder.mPic = (ImageView)view.findViewById(R.id.ins_small_pic);
- final int p = position;
- viewMap.put(position, view);
- view.setTag(holder);
- }else{
- Log.e("MainActivity","position2 = "+position);
- view = viewMap.get(position);
- holder = (ViewHolder)view.getTag();
- }
-
- data ins = mList.get(position);
- holder.mTitle.setText(ins.getTitle());
-
-
- holder.mPic.setVisibility(View.VISIBLE);
-
-
- Drawable cachedImage = imageLoader.loadDrawable(ins.getPic(), holder.mPic,
- new ImageCallback() {
- public void imageLoaded(Drawable imageDrawable,
- ImageView imageView, String imageUrl) {
- imageView.setImageDrawable(imageDrawable);
- }
- });
- if (cachedImage != null) {
- holder.mPic.setImageDrawable(cachedImage);
- }
-
- return view;
-
- }
-
-
- static class ViewHolder{
- ImageView mPic;
- TextView mTitle;
- TextView mTime;
- TextView mType;
- }
- }
原理简单,不罗嗦了
本地缓存
就是先读取本地的数据,如果本地没有再从网络上获取
WebView中很简单,
-
- mWebView.getSettings().setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK);
就能实现了。
其他地方我们就得自己写一个异步图片下载了,
- public class AsyncImageLoader {
-
-
- private static HashMap<String, SoftReference<Drawable>> imageCache;
-
- static {
- imageCache = new HashMap<String, SoftReference<Drawable>>();
- }
-
-
- public AsyncImageLoader() {
-
- }
- public Drawable loadDrawable(final String imageUrl,final ImageView imageView, final ImageCallback imageCallback){
- if (imageCache.containsKey(imageUrl)) {
-
- SoftReference<Drawable> softReference = imageCache.get(imageUrl);
- Drawable drawable = softReference.get();
- if (drawable != null) {
- return drawable;
- }
- }
- final Handler handler = new Handler() {
- public void handleMessage(Message message) {
- imageCallback.imageLoaded((Drawable) message.obj, imageView,imageUrl);
- }
- };
-
- new Thread() {
- @Override
- public void run() {
- Drawable drawable = null;
- try {
- drawable = ImageUtil.geRoundDrawableFromUrl(imageUrl, 20);
- } catch (Exception e) {
- e.printStackTrace();
- }
- imageCache.put(imageUrl, new SoftReference<Drawable>(drawable));
- Message message = handler.obtainMessage(0, drawable);
- handler.sendMessage(message);
- }
- }.start();
- return null;
- }
-
- public interface ImageCallback {
- public void imageLoaded(Drawable imageDrawable,ImageView imageView, String imageUrl);
- }
- }
当然我们也可以存数据库中,从数据库中优先获取,当没有网络的时候达到离线阅读的功能。