`
hunankeda110
  • 浏览: 741729 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

android中异步加载图片

阅读更多
浅谈Android ListView 异步图片获取




         Android应用中,从远程获取图片算是经常要用的一个功能,而图片资源往往会消耗比较大的流量,而且如果加载在图片比较多的View中,如ListView GridView WebView中,加载速度会比较缓慢。Android中图片加载速度很慢的话,程序很容易就挂掉,等待的用户用户同样会等到崩溃。

我们一般的处理方法是:



异步下载


本地缓存



-----------------------------------------------------------
先说异步下载






如一个ListView的异步下载



Java代码 
1.public class AsyncActivity extends Activity  {  
2.    List<data> insList;  
3.    private ListView mListView;  
4.    private ArrayList<data> mListItems;  
5.    private ItemAdapter mAdapter;  
6.    private ImageView mLfteView;  
7.    private ImageView mRightView;  
8.      
9.      
10. 
11.    private static final int REFRESH_LIST = 1;  
12.    Handler mHandler = new Handler() {  
13.        public void handleMessage(android.os.Message msg) {  
14.            int type = msg.what;  
15.            switch (type) {  
16.            case REFRESH_LIST: {  
17.              
18.                if (mListItems.size() > 0) {  
19.                    mListView.setVisibility(View.VISIBLE);  
20.                    if (mAdapter== null) {  
21.                        mAdapter = new Adapter(AsyncActivity.this,  
22.                                mListItems);  
23.                        mListView.setAdapter(mAdapter);  
24.                    }  
25.                        mAdapter.notifyDataSetChanged();  
26. 
27.                }  
28.                mListView.requestFocus();  
29.                  
30.                unShowDialogLoading();  
31.                break;  
32.            }  
33. 
34.          
35.            default:  
36.                break;  
37.            }  
38.        };  
39.    };  
40. 
41.      
42.    public void onCreate(Bundle savedInstanceState) {   
43.        super.onCreate(savedInstanceState);   
44.        setContentView(R.layout.insurance_list);   
45.        initViews();  
46.        getList();  
47.    }   
48.    
49.    /** 
50.     * 初始化view 
51.     */ 
52.    private void initViews(){  
53.          
54.        mListView = (ListView)findViewById(R.id.list);  
55.        mListView.setAdapter(mAdapter);  
56.        mListView.setOnItemClickListener(new OnItemClickListener(){  
57.            public void onItemClick(AdapterView<?> arg0, View v, int id,  
58.                    long pos) {  
59.                // 获得被单击的项       
60.                //跳转  
61.              
62.            }  
63.        });  
64.     
65.          
66.        mListItems = new ArrayList<data>();  
67. 
68.    }  
69. 
70.      
71.    
72.    private void getList() {  
73.        showDialogLoading();  
74.         //得到保险列表  
75.        insuranceData insurance = new insuranceData();  
76.        insList = insurance.getList();  
77.        mListItems.clear();  
78.        mListItems.addAll(insList);  
79.        mHandler.sendEmptyMessage(REFRESH_LIST);  
80.          
81.          
82.    }  
83.      
84. 
85.    private ProgressDialog mLoadingDialog;  
86. 
87.    private void showDialogLoading() {  
88.        mLoadingDialog = new ProgressDialog(this);                   
89.        mLoadingDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);  
90.         //spinner  自旋体 像螺旋桨那样                               
91.        mLoadingDialog.setMessage("载入中,请稍候...");                   
92.        mLoadingDialog.setIndeterminate(false);//设置进度条是否为不明确                  
93.        mLoadingDialog.setCancelable(true);//设置进度条是否可以按退回健取消                                 
94.        mLoadingDialog.show();   
95.    }  
96. 
97.    private void unShowDialogLoading() {  
98.        if (mLoadingDialog == null)  
99.            return;  
100.        else 
101.            mLoadingDialog.dismiss();  
102.    }  
103.      
104.} 
public class AsyncActivity extends Activity  {
List<data> insList;
private ListView mListView;
private ArrayList<data> mListItems;
private ItemAdapter mAdapter;
private ImageView mLfteView;
private ImageView mRightView;



private static final int REFRESH_LIST = 1;
Handler mHandler = new Handler() {
public void handleMessage(android.os.Message msg) {
int type = msg.what;
switch (type) {
case REFRESH_LIST: {

if (mListItems.size() > 0) {
mListView.setVisibility(View.VISIBLE);
if (mAdapter== null) {
mAdapter = new Adapter(AsyncActivity.this,
mListItems);
mListView.setAdapter(mAdapter);
}
mAdapter.notifyDataSetChanged();

}
mListView.requestFocus();

unShowDialogLoading();
break;
}


default:
break;
}
};
};


    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.insurance_list);
        initViews();
        getList();
    }
 
    /**
     * 初始化view
     */
    private void initViews(){
   
    mListView = (ListView)findViewById(R.id.list);
    mListView.setAdapter(mAdapter);
    mListView.setOnItemClickListener(new OnItemClickListener(){
public void onItemClick(AdapterView<?> arg0, View v, int id,
long pos) {
    // 获得被单击的项    
        //跳转
   
}
    });
  
   
    mListItems = new ArrayList<data>();

    }

   
 
    private void getList() {
    showDialogLoading();
    //得到保险列表
        insuranceData insurance = new insuranceData();
        insList = insurance.getList();
        mListItems.clear();
        mListItems.addAll(insList);
        mHandler.sendEmptyMessage(REFRESH_LIST);
       
       
    }
   

    private ProgressDialog mLoadingDialog;

private void showDialogLoading() {
mLoadingDialog = new ProgressDialog(this);                
mLoadingDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
//spinner  自旋体 像螺旋桨那样                            
mLoadingDialog.setMessage("载入中,请稍候...");                
mLoadingDialog.setIndeterminate(false);//设置进度条是否为不明确               
mLoadingDialog.setCancelable(true);//设置进度条是否可以按退回健取消                              
mLoadingDialog.show();
}

private void unShowDialogLoading() {
if (mLoadingDialog == null)
return;
else
mLoadingDialog.dismiss();
}

}

它的Adapter是




Java代码 
1.public class InsuranceItemAdapter extends BaseAdapter{  
2.    private ArrayList<data> mList;  
3.    private Context mContext;  
4.    // 异步加载图片的线程  
5.    private AsyncImageLoader imageLoader = new AsyncImageLoader();  
6.    //当前的缓存  
7.    private Map<Integer, View> viewMap = new HashMap<Integer, View>();  
8. 
9.    public InsuranceItemAdapter(Context context, ArrayList<data> ins) {  
10.        mContext = context;  
11.        mList= ins;  
12.    }  
13. 
14.    public InsuranceItemAdapter(Context context, ArrayList<data> ins,  
15.            Handler handler) {  
16.        mContext = context;  
17.        mList= ins;  
18.    }  
19. 
20.    public void setInsurance(ArrayList<data> ins) {  
21.        mList= ins;  
22.    }  
23.      
24.      
25.      
26.    public int getCount() {  
27.        return mList.size();  
28.    }  
29. 
30.    public Object getItem(int position) {  
31.        try {  
32.            return mList.get(position);  
33.        } catch (Exception ex) {  
34.            return null;  
35.        }  
36.    }  
37. 
38.    public long getItemId(int position) {  
39.        return position;  
40.    }  
41. 
42.      
43.    private View newView() {  
44.        ItemView view = new ItemView(mContext);  
45.        return view;  
46.    }  
47.      
48.      
49.      
50.    public View getView(int position, View convertView, ViewGroup parent) {  
51.        //先从缓存里面读取  
52.        ViewHolder holder = null;    
53.        View view;    
54.          
55.         if (viewMap.get(position) == null) {    
56.            view = newView();  
57.            holder = new ViewHolder();    
58.            holder.mTitle = (TextView)view.findViewById(R.id.ins_title);  
59.            holder.mTime = (TextView)view.findViewById(R.id.ins_time);  
60.            holder.mType = (TextView)view.findViewById(R.id.ins_from);  
61.            holder.mPic = (ImageView)view.findViewById(R.id.ins_small_pic);  
62.            final int p = position;    
63.            viewMap.put(position, view);    
64.            view.setTag(holder);    
65.         }else{  
66.             Log.e("MainActivity","position2 = "+position);    
67.             view = viewMap.get(position);    
68.             holder = (ViewHolder)view.getTag();    
69.         }  
70.          
71.         data ins = mList.get(position);  
72.         holder.mTitle.setText(ins.getTitle());  
73. 
74.          
75.        holder.mPic.setVisibility(View.VISIBLE);  
76.          
77.        // 异步加载图片  
78.        Drawable cachedImage = imageLoader.loadDrawable(ins.getPic(), holder.mPic,  
79.                new ImageCallback() {  
80.                    public void imageLoaded(Drawable imageDrawable,  
81.                            ImageView imageView, String imageUrl) {  
82.                        imageView.setImageDrawable(imageDrawable);  
83.                    }  
84.                });  
85.        if (cachedImage != null) {  
86.            holder.mPic.setImageDrawable(cachedImage);  
87.        }  
88.           
89.         return view;    
90. 
91.    }  
92.      
93.      
94.    static class ViewHolder{    
95.        ImageView mPic;  
96.        TextView mTitle;  
97.        TextView mTime;  
98.        TextView mType;  
99.    }  
100.} 
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中很简单,


Java代码 
1.//优先缓存  
2.        mWebView.getSettings().setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK); 
//优先缓存
mWebView.getSettings().setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK); 就能实现了。





其他地方我们就得自己写一个异步图片下载了,


Java代码 
1.public class AsyncImageLoader {  
2. 
3.     //SoftReference是软引用,是为了更好的为了系统回收变量  
4.    private static HashMap<String, SoftReference<Drawable>> imageCache;  
5.      
6.    static {  
7.        imageCache = new HashMap<String, SoftReference<Drawable>>();  
8.    }  
9.      
10.      
11.    public AsyncImageLoader() {  
12.          
13.    }  
14.    public Drawable loadDrawable(final String imageUrl,final ImageView imageView, final ImageCallback imageCallback){  
15.        if (imageCache.containsKey(imageUrl)) {  
16.            //从缓存中获取  
17.            SoftReference<Drawable> softReference = imageCache.get(imageUrl);  
18.            Drawable drawable = softReference.get();  
19.            if (drawable != null) {  
20.                return drawable;  
21.            }  
22.        }  
23.        final Handler handler = new Handler() {  
24.            public void handleMessage(Message message) {  
25.                imageCallback.imageLoaded((Drawable) message.obj, imageView,imageUrl);  
26.            }  
27.        };  
28.        //建立新一个新的线程下载图片  
29.        new Thread() {  
30.            @Override 
31.            public void run() {  
32.                Drawable drawable = null;  
33.                try {  
34.                    drawable = ImageUtil.geRoundDrawableFromUrl(imageUrl, 20);  
35.                } catch (Exception e) {  
36.                    e.printStackTrace();  
37.                }  
38.                imageCache.put(imageUrl, new SoftReference<Drawable>(drawable));  
39.                Message message = handler.obtainMessage(0, drawable);  
40.                handler.sendMessage(message);  
41.            }  
42.        }.start();  
43.        return null;  
44.    }  
45.    //回调接口  
46.    public interface ImageCallback {  
47.        public void imageLoaded(Drawable imageDrawable,ImageView imageView, String imageUrl);  
48.    }  
49.} 
public class AsyncImageLoader {

//SoftReference是软引用,是为了更好的为了系统回收变量
    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);
    }
}



当然我们也可以存数据库中,从数据库中优先获取,当没有网络的时候达到离线阅读的功能。

分享到:
评论
2 楼 guanting207 2013-12-19  
trx999 写道
建议一下。关键代码可以贴出来。所有的不必要的代码贴出来只能让阅读者眼花缭乱,甚至思维混乱。你可以把小demo上传。思路清楚了,代码看起来就清楚了。

1 楼 trx999 2012-04-24  
建议一下。关键代码可以贴出来。所有的不必要的代码贴出来只能让阅读者眼花缭乱,甚至思维混乱。你可以把小demo上传。思路清楚了,代码看起来就清楚了。

相关推荐

Global site tag (gtag.js) - Google Analytics