您的位置:首页 > 理论基础 > 计算机网络

【Android】网络图片加载优化(一)利用弱引用缓存异步加载

2013-11-08 23:27 591 查看

应用背景

ListView 或GridView是一种可以显示一系列项目并能进行滚动显示的 View,每一行的Item可能包含复杂的结构。

其可能会从网络上获取一些图片信息,就现在的网络速度要想保持ListView运行的很好滚动流畅是做不到的。

所以这里就需要把这些信息利用多线程实现异步加载,同时,应用弱引用缓存技术方便再次加载时预览。

工作原理

使用了SoftReference来缓存图片,允许 GC在需要的时候可以对缓存中的图片进行清理。

它是这样工作:

(1) 调用 loadDrawable(ImageUrl, imageCallback),传入一个匿名实现的 ImageCallback接口;

(2)如果图片在缓存中不存在的话,图片将从单一的线程中下载并在下载结束时通过 ImageCallback回调;

(3)如果图片确实存在于缓存中,就会马上返回,不会回调 ImageCallback。

弱应用缓存类的封装

package com.wei.util;

import java.lang.ref.SoftReference;
import java.net.URL;
import java.util.HashMap;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Handler;
import android.os.Message;

public class AsyncImageLoader{
Bitmap bitmap = null;
HashMap<String, SoftReference<Bitmap>> imageCache;
BitmapFactory.Options opts;
// 1.根据URL返回Drawable的函数
// 2.工具类的核心函数,包含handler+thread

public AsyncImageLoader() {
imageCache = new HashMap<String, SoftReference<Bitmap>>();
opts = new BitmapFactory.Options();
opts.inSampleSize = 0;    //这个的值压缩的倍数(2的整数倍),数值越小,压缩率越小,图片越清晰
}

public Bitmap asyncLoadImage(final String strUrl, final int i, final LoadFinishCallBack loadFinishCallBack) {
Bitmap bitmap = null;
//首先判断Map中是否有这种图片的缓存,若有,直接返回该图片的引用
if(imageCache.containsKey(strUrl)) {
SoftReference<Bitmap> softReference = imageCache.get(strUrl);
bitmap = softReference.get();
if(bitmap != null) {
return bitmap;
}
}

final Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
// 回调接口
loadFinishCallBack.loadFinish(strUrl, i, (Bitmap) msg.obj);
}
};

new Thread() {
@Override
public void run() {
Bitmap bitmap = null;
try {
bitmap = BitmapFactory.decodeStream(new URL(strUrl).openConnection().getInputStream(), null, opts);
} catch (Exception e) {
e.printStackTrace();
}
imageCache.put(strUrl, new SoftReference<Bitmap>(bitmap));//第一次拿某张图片,把该图片的引用放入缓存中
Message msg = new Message();
msg.obj = bitmap;
//System.out.println("bitmap 宽高"+bitmap.getWidth()+"-"+bitmap.getHeight());
handler.sendMessage(msg);
}
}.start();

return bitmap;
}

public interface LoadFinishCallBack {
public void loadFinish(String strUrl, int i, Bitmap bitmap);
}
}


弱引用缓存类的应用

Bitmap bm = asyncImageLoader.asyncLoadImage(strUrl, 0, callback);
oneView.image.setImageBitmap(null);
if(bm==null) {
oneView.image.setBackgroundResource(R.drawable.slt);
} else {
oneView.image.setImageBitmap(bm);
}

其中,asyncImageLoader是上述封装类的实例,R.drawable.slt是图片未加载出来时显示的图片资源。
callback是所调用的接口:

//图片下载成功后执行的回调接口
LoadFinishCallBack callback = new LoadFinishCallBack() {
@Override
public void loadFinish(String strUrl, int i, Bitmap bitmap) {
if (bitmap != null) {
ImageView imageView = (ImageView) gridView.findViewWithTag(strUrl);
if(imageView != null) {
imageView.setImageBitmap(bitmap);
}
}
};
};


应用举例

package com.wei.adapter;

import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import com.wei.util.AsyncImageLoader;
import com.wei.util.MyApplication;
import com.wei.util.MyImgCache;
import com.wei.util.MyThread;
import com.wei.util.AsyncImageLoader.LoadFinishCallBack;
import com.wei.wotao.FavorActivity;
import com.wei.wotao.R;
import com.wei.wotao.WebViewActivity;

import android.R.integer;
import android.app.Application;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.graphics.Bitmap;
import android.graphics.Paint;
import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.GridView;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

public class FavorAdapter extends BaseAdapter{
private LayoutInflater mInflater;// 动态布局映射
private JSONArray list;
private Context context;
GridView gridView;
private int i = 0;
AsyncImageLoader asyncImageLoader;
int itemWidth;
private String nickname;
public FavorAdapter(JSONArray list,GridView gridView,Context context,String nickname){
this.list = list;
this.context = context;
this.gridView = gridView;
this.mInflater = LayoutInflater.from(context);
itemWidth = MyApplication.screenWidth/2;
asyncImageLoader  = new AsyncImageLoader();
this.nickname = nickname;
//		SharedPreferences share = getSharedPreferences("logInfo", 2);
//		nickname = share.getString("username", "");
}
public void setList(JSONArray list) {
this.list = list;
}
public JSONArray getList() {
return list;
}
@Override
public int getCount() {
// TODO Auto-generated method stub
return list.length();
}

@Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return null;
}

@Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return 0;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
OneView oneView;
if (convertView == null) {
convertView = mInflater.inflate(R.layout.subitem_item_grid_favor2, null);//根据布局文件实例化view
oneView = new OneView();
oneView.promotion_price = (TextView) convertView.findViewById(R.id.promotion_price);//找某个控件
oneView.price = (TextView) convertView.findViewById(R.id.price);
oneView.sub_price = (TextView) convertView.findViewById(R.id.sub_price);
oneView.image = (ImageView) convertView.findViewById(R.id.image);
oneView.remove = (Button) convertView.findViewById(R.id.remove);
convertView.setTag(oneView);//把View和某个对象关联起来
} else {
oneView = (OneView) convertView.getTag();
}
JSONObject jObject = null;
try {
jObject = list.getJSONObject(position);//根据position获取集合类中某行数据
oneView.promotion_price.setText("现价¥"+jObject.get("promotion_price").toString());//给该控件设置数据(数据从集合类中来)
oneView.price.setText("原价¥"+jObject.get("price").toString());
oneView.price.getPaint().setFlags(Paint. STRIKE_THRU_TEXT_FLAG);
Float float1 = Float.valueOf(jObject.get("price").toString())- Float.valueOf(jObject.get("promotion_price").toString());
if (float1 == 0) {
oneView.sub_price.setVisibility(View.INVISIBLE);
}
oneView.sub_price.setText(float1.toString()+" ");
String strUrl = jObject.get("pic_url").toString() + "_310x310.jpg";
oneView.image.setTag(strUrl);
Bitmap bm = asyncImageLoader.asyncLoadImage(strUrl, 0, callback);
oneView.image.setImageBitmap(null);
if(bm==null) {
oneView.image.setBackgroundResource(R.drawable.slt);
} else {
oneView.image.setImageBitmap(bm);
}
bm = null;
final String itemID = jObject.get("itemID").toString();
oneView.remove.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
new MyThread("favor.php?frm=3g&action=favorOrCancel&nickname=" + nickname
+"&id="+itemID+"&type=sp&favor=0", 0, handler).start();
Toast.makeText(context, "取消成功"+nickname, 1000).show();

}
});
} catch (Exception e) {
// TODO: handle exception
}
return convertView;
}
/** 把每行布局文件的各个控件包装成一个对象  */
private class OneView{
TextView promotion_price;
TextView price;
TextView sub_price;
ImageView image;
Button remove;
}
//图片下载成功后执行的回调接口
LoadFinishCallBack callback = new LoadFinishCallBack() {
@Override
public void loadFinish(String strUrl, int i, Bitmap bitmap) {
if (bitmap != null) {
ImageView imageView = (ImageView) gridView.findViewWithTag(strUrl);
if(imageView != null) {
imageView.setImageBitmap(bitmap);
}
}
};
};
private Handler handler = new Handler() {
public void handleMessage(android.os.Message msg) {
if (msg.what == 0){
String string = (String) msg.obj;
if("1".equals(string)){
Toast.makeText(context, "取消成功", 1000).show();
}
}
};
};
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐