浅谈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);
}
}.start();
return null;
}
//回调接口
public interface ImageCallback {
public void imageLoaded(Drawable imageDrawable,ImageView imageView, String imageUrl);
}
}
当然我们也可以存数据库中,从数据库中优先获取,当没有网络的时候达到离线阅读的功能。
<!--EndFragment-->