Android ListView异步加载图片错位解决方案一 使用findViewWithTag

* 解决listView 加载图片错位解决方案一 使用findViewWithTag *
使用findViewWithTag必须要有ListView的实例,在Adapter中怎样才能获取到ListView的实例呢?,getView()方法中传入的第三个参数其实就是ListView的实例 我们定义一个全局变量mListView ,然后在getView()方法中判断它是否为空, 如果为空就把parent这个参数赋值给它。
,,另外一个操作就是在getView()方法中我们调用了ImageView的setTag()方法,并把当前位置图片的URL地址作为参数传了进去,这个是为后续的findViewWithTag()方法做准备.
最后,我们修改了BitmapWorkerTask的构造函数,这里不再通过构造函数把ImageView的实例传进去了,而是在onPostExecute()方法当中通过ListView的findVIewWithTag()方法来去获取ImageView控件的实例。获取到控件实例后判断下是否为空,如果不为空就让图片显示到控件上。

显示图片的 Adapter

package com.gaoo.listviewtest;

/**
 * 1.设置布局文件主界面 listview 和新建一个 item 布局
 * 2.新建ImageAdapter做为ListView的适配器
 *
 * 解决listView 加载图片错位
 * 解决方案一  使用findViewWithTag
 */
public class ImageAdapter extends ArrayAdapter<String> {
private ListView mListView; //定义一个全局变量 listview
    /**
     * 图片缓存技术的核心类 ,用于缓存所有下载的图片,在程序内存达到设定值时,会将最少最近使用的图片移除掉.
     */
    private LruCache<String, BitmapDrawable> mMemoryCache;

    public ImageAdapter(Context context, int resource, String[] objects) {
        super(context, resource, objects);
        //获取应用程序的最大可用内存
        int maxMemory = (int) Runtime.getRuntime().maxMemory();
        //大小为当前程序运行时内存的1/8
        int cacheSize = maxMemory / 8;
        mMemoryCache = new LruCache<String, BitmapDrawable>(cacheSize) {
            @Override
            protected int sizeOf(String key, BitmapDrawable value) {
                return value.getBitmap().getByteCount();
            }
        };
    }
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        // 第1.解决方案一  使用findViewWithTag
        if (mListView == null) {
            mListView = (ListView) parent;
        }
        String url = getItem(position); //根据当前的位置获取到图片的URL地址

        View view;
        if (convertView == null) {
            view = LayoutInflater.from(getContext()).inflate(R.layout.item_image, null);
        } else {
            view = convertView;
        }
        ImageView imageView = (ImageView) view.findViewById(R.id.image);

        //第2.解决方案一  使用findViewWithTag
        imageView.setImageResource(R.drawable.empty_photo);
        imageView.setTag(url);

        //先从缓存中获取
        BitmapDrawable drawable = getBitmapFromMemoryCache(url);
        if (drawable != null) {
            imageView.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 url LruCache的键,传入图片的URL地址。
     * @return
     */
    public BitmapDrawable getBitmapFromMemoryCache(String url) {
        return mMemoryCache.get(url);
    }
    /**
     * 异步下载图片的任务。
     */
    private class BitmapWorkerTask extends AsyncTask<String, Void, BitmapDrawable> {
        private ImageView mImageView;
        private String mImageUrl;
//        public BitmapWorkerTask(ImageView imageView) {
//            this.mImageView = imageView;
//        }
        @Override
        protected BitmapDrawable doInBackground(String... params) {
            mImageUrl = params[0];
            Log.d("BitmapWorkerTask-------", "从网络上获取");
            //在后台 开始下载图片
            Bitmap bitmap = downloadBitmap(mImageUrl);
            BitmapDrawable drawable = new BitmapDrawable(getContext().getResources(), bitmap);
            addBitmapToMemoryCache(mImageUrl, drawable);
            return drawable;
        }
        @Override
        protected void onPostExecute(BitmapDrawable drawable) {
            //第3.解决方案一  使用findViewWithTag
            ImageView imageView = (ImageView) mListView.findViewWithTag(mImageUrl);
            if (imageView != null && drawable != null) {
                imageView.setImageDrawable(drawable);
            }
//            if (mImageView != null && drawable != null) {
//                mImageView.setImageDrawable(drawable);
//            }
        }
        /**
         * 建立网络请求,并获取 bitmap 对象
         *
         * @param imageUrl 图片的URL地址
         * @return
         */
        private Bitmap downloadBitmap(String imageUrl) {
            Bitmap bitmap = null;
            HttpURLConnection urlConnection = null;
            try {
                URL url = new URL(imageUrl);
   urlConnection = (HttpURLConnection)url.openConnection();
                urlConnection.setConnectTimeout(20 * 1000);
                urlConnection.setReadTimeout(10 * 1000);
                InputStream is = urlConnection.getInputStream();
                bitmap = BitmapFactory.decodeStream(is);
            } catch (MalformedURLException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                if (urlConnection != null) {
                    urlConnection.disconnect();
                }
            }

            return bitmap;
        }
    }
}

主界面

/**
 * Android ListView异步加载图片乱序问题,原因分析及解决方案
 * 原文地址 : http://blog.csdn.net/guolin_blog/article/details/45586553
ImageId 图片资源可以在 原文地址 中 查找
 */
public class MainActivity extends AppCompatActivity {
    ListView listView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        listView = (ListView) findViewById(R.id.list_view);

//        //方法3 解决方案一 使用findViewWithTag
        ImageAdapter adapter = new ImageAdapter(this,0, ImageId.imageUrl);
        listView.setAdapter(adapter);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值