浏览 5974 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (1) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2012-02-22
浅谈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(); //得到保险列表 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是
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 { //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); } }
当然我们也可以存数据库中,从数据库中优先获取,当没有网络的时候达到离线阅读的功能。
<!--EndFragment--> 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2012-02-22
没什么技术含量,属于重复帖
|
|
返回顶楼 | |
发表时间:2012-02-25
确实,抄来抄去的,根本没深入研究。
|
|
返回顶楼 | |
发表时间:2012-02-29
难道比原文的代码更精简吗?
|
|
返回顶楼 | |