浅谈Android ListView 异步图片获取
Android应用中,从远程获取图片算是经常要用的一个功能,而图片资源往往会消耗比较大的流量,而且如果加载在图片比较多的View中,如ListView GridView WebView中,加载速度会比较缓慢。Android中图片加载速度很慢的话,程序很容易就挂掉,等待的用户用户同样会等到崩溃。
我们一般的处理方法是:
异步下载
本地缓存
-----------------------------------------------------------
先说异步下载
如一个ListView的异步下载
- 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();
- //得到列表
- Data ins = new Data();
- insList = ins.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是
- public class ItemAdapter 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() {
- InsItemView insView = new InsItemView(mContext);
- return insView;
- }
- 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);
就能实现了。
其他地方我们就得自己写一个异步图片下载了,
- package cn.ethink.activity.net;
- import java.lang.ref.SoftReference;
- import java.util.HashMap;
- import android.graphics.drawable.Drawable;
- import android.os.Handler;
- import android.os.Message;
- import android.widget.ImageView;
- import cn.ethink.activity.view.utils.ImageUtil;
- 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);