ListView图片优化(一)---findViewWithTag

Android基础 专栏收录该内容
136 篇文章 0 订阅

转自 郭霖

由于使用findViewWithTag必须要有ListView的实例才行,那么我们在Adapter中怎样才能拿到ListView的实例呢?getView()方法中传入的第三个参数其实就是ListView的实例,那么这里我们定义一个全局变量mListView,然后在getView()方法中判断它是否为空,如果为空就把parent这个参数赋值给它。

另外在getView()方法中我们还做了一个操作,就是调用了ImageView的setTag()方法,并把当前位置图片的URL地址作为参数传了进去,这个是为后续的findViewWithTag()方法做准备。

这里我们可以尝试分析一下findViewWithTag的工作原理,其实顾名思义,这个方法就是通过Tag的名字来获取具备该Tag名的控件,我们先要调用控件的setTag()方法来给控件设置一个Tag,然后再调用ListView的findViewWithTag()方法使用相同的Tag名来找回控件。

那么为什么用了findViewWithTag()方法之后,图片就不会再出现乱序情况了呢?其实原因很简单,由于ListView中的ImageView控件都是重用的,移出屏幕的控件很快会被进入屏幕的图片重新利用起来,那么getView()方法就会再次得到执行,而在getView()方法中会为这个ImageView控件设置新的Tag,这样老的Tag就会被覆盖掉,于是这时再调用findVIewWithTag()方法并传入老的Tag,就只能得到null了,而我们判断只有ImageView不等于null的时候才会设置图片,这样图片乱序的问题也就不存在了。


ImageAdapter

package com.example.listviewyouhua;

import java.net.HttpURLConnection;
import java.net.URL;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.BitmapDrawable;
import android.os.AsyncTask;
import android.support.v4.util.LruCache;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.ListView;

public class ImageAdapter extends ArrayAdapter<String> {

	/**
	 * 图片缓存技术的核心类,用于缓存所有下载好的图片,在程序内存达到设定值时会将最少最近使用的图片移除掉。
	 */
	private LruCache<String, BitmapDrawable> mMemoryCache;
	private ListView mListView;
	/**
	 * 构造方法:获取图片缓存的大小内存
	 * 
	 * @param context
	 * @param resource
	 * @param objects
	 */
	public ImageAdapter(Context context, int resource, String[] objects) {
		super(context, resource, objects);
		// 获取应用程序最大可用内存
		int maxMemory = (int) Runtime.getRuntime().maxMemory();
		int cacheSize = maxMemory / 8;
		mMemoryCache = new LruCache<String, BitmapDrawable>(cacheSize) {
			@Override
			protected int sizeOf(String key, BitmapDrawable drawable) {
				return drawable.getBitmap().getByteCount();
			}
		};
	}
	@Override  
    public View getView(int position, View convertView, ViewGroup parent) {  
        if (mListView == null) {    
            mListView = (ListView) parent;    
        }   
        String url = getItem(position);  
        View view;  
        if (convertView == null) {  
            view = LayoutInflater.from(getContext()).inflate(R.layout.image_item, null);  
        } else {  
            view = convertView;  
        }  
        ImageView image = (ImageView) view.findViewById(R.id.image);  
        image.setImageResource(R.drawable.ic_launcher);  
        ///关键代码///
        image.setTag(url);  
        BitmapDrawable drawable = getBitmapFromMemoryCache(url);  
        if (drawable != null) {  
            image.setImageDrawable(drawable);  
        } else {  
            BitmapWorkerTask task = new BitmapWorkerTask();  
            task.execute(url);  
        }  
        return view;  
    }  

	/**
	 * 将一张图片存储到LruCache中。
	 * 
	 * @param key
	 *            LruCache的键,这里传入图片的URL地址。
	 * @param drawable
	 *            LruCache的值,这里传入从网络上下载的BitmapDrawable对象。
	 */
	public void addBitmapToMemoryCache(String key, BitmapDrawable drawable) {
		if (getBitmapFromMemoryCache(key) == null) {
			mMemoryCache.put(key, drawable);
		}
	}

	/**
	 * 从LruCache中获取一张图片,如果不存在就返回null。
	 * 
	 * @param key
	 *            LruCache的键,这里传入图片的URL地址。
	 * @return 对应传入键的BitmapDrawable对象,或者null。
	 */
	public BitmapDrawable getBitmapFromMemoryCache(String key) {
		return mMemoryCache.get(key);
	}

	/**
	 * 异步下载图片的任务。
	 * 
	 * @author guolin
	 */
	class BitmapWorkerTask extends AsyncTask<String, Void, BitmapDrawable> {

		 String imageUrl;   

		public BitmapWorkerTask() {
		}

		@Override  
        protected BitmapDrawable doInBackground(String... params) {  
            imageUrl = params[0];  
            // 在后台开始下载图片  
            Bitmap bitmap = downloadBitmap(imageUrl);  
            BitmapDrawable drawable = new BitmapDrawable(getContext().getResources(), bitmap);  
            addBitmapToMemoryCache(imageUrl, drawable);  
            return drawable;  
        }  
  
        @Override  
        protected void onPostExecute(BitmapDrawable drawable) {  
            ImageView imageView = (ImageView) mListView.findViewWithTag(imageUrl);    
            if (imageView != null && drawable != null) {    
                imageView.setImageDrawable(drawable);    
            }   
        }  

		/**
		 * 建立HTTP请求,并获取Bitmap对象。
		 * 
		 * @param imageUrl
		 *            图片的URL地址
		 * @return 解析后的Bitmap对象
		 */
		private Bitmap downloadBitmap(String imageUrl) {
			Bitmap bitmap = null;
			HttpURLConnection con = null;
			try {
				URL url = new URL(imageUrl);
				con = (HttpURLConnection) url.openConnection();
				con.setConnectTimeout(5 * 1000);
				con.setReadTimeout(10 * 1000);
				bitmap = BitmapFactory.decodeStream(con.getInputStream());
			} catch (Exception e) {
				e.printStackTrace();
			} finally {
				if (con != null) {
					con.disconnect();
				}
			}
			return bitmap;
		}

	}

}


  • 0
    点赞
  • 0
    评论
  • 1
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

打赏
文章很值,打赏犒劳作者一下
相关推荐
©️2020 CSDN 皮肤主题: 编程工作室 设计师:CSDN官方博客 返回首页

打赏

进击的小猿

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值