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是图片未加载出来时显示的图片资源。
//图片下载成功后执行的回调接口 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(); } } }; }; }