zoukankan      html  css  js  c++  java
  • listview前几个item的图片怎么是空白的、listview更新了ui不起作用、在handler里更新了UI不起作用

    不是不起作用,不信你可以在更新ui代码附近加输出的log,说明程序是跑到那里了。但是未达到我们的想要的效果。

    我们知道在listview里更新UI,listview的适配器Adapter里有个getView方法,在里面通常我们更新UI都是对holder里的控件更新。

    代码如下:

                @Override
                public View getView(final int position, View convertView,
                        ViewGroup parent) {
                    if (convertView == null) {
                        convertView = View.inflate(getApplicationContext(),R.layout.list_item, null);
                        holder = new ViewHolder();
                        holder.ivImage = (ImageView) convertView.findViewById(R.id.iv_image);
                        convertView.setTag(holder);
                    } else {
                        holder = (ViewHolder) convertView.getTag();
                    }
                    holder.ivImage.setImageBitmap(bitmap);//更新UI
                    return convertView;
                 }

    但有时候我们要执行一些耗时操作,比如请求网络下载图片、从sdcard读取并压缩图片,我们就必须得另开子线程去执行。代码如下:

                @Override
                public View getView(final int position, View convertView,
                        ViewGroup parent) {
                    if (convertView == null) {
                        convertView = View.inflate(getApplicationContext(),R.layout.list_item, null);
                        holder = new ViewHolder();
                        holder.ivImage = (ImageView) convertView.findViewById(R.id.iv_image);
                        convertView.setTag(holder);
                    } else {
                        holder = (ViewHolder) convertView.getTag();
                    }
                    bitmap = mMemoryCacheUtils.getMemoryCache(list.get(position));
                    if (bitmap != null) {
                        // 从内存获取
                        holder.ivImage.setImageBitmap(bitmap);// 更新UI
                    } else {
                        // 从sdcard获取
                        new Thread() {
                            public void run() {
                                compressBitmap = BitmapUtil.compressPicture(list.get(position), 120, 60);//获取sdcard图片并压缩
                                if (compressBitmap != null) {
                                    mMemoryCacheUtils.setMemoryCache(list.get(position), compressBitmap);
                                    mHandler.post(new Runnable() {
                                        public void run() {
                                            holder.ivImage.setImageBitmap(compressBitmap);// 更新UI
                                        }
                                    });
                                }
                            }
                        }.start();
                    return convertView;
                }

    从上面红色代码处得知,开启了子线程去获取并压缩图片,然后将该图片设置给imageview,而且也是执行在handler里,更新UI应该没问题啊,可是得出的效果图就是前几个item的图片都没有展示出来:

    把listview往上滑可以看到后面的图片却可以展示出来。

    通过log输出也确实跑到了红色代码那里,但是却没达到理想效果。我当时几近崩溃,抓狂的啊,网上搜索也没有类似问题。后来想了一下,既然代码都跑到这了,为什么更新UI却没反应呢?有可能是更新错了地方了。也正因为咱们新开了子线程,而且执行了耗时操作,那么跑到红色代码那里的时候getView这个方法都走了好几遍了。所以holder里的ivImage也不是当时的item的imageview。所以要找个方法来保存这个imageview。所以代码换成如下的:

                @Override
                public View getView(final int position, View convertView,
                        ViewGroup parent) {
                    if (convertView == null) {
                        convertView = View.inflate(getApplicationContext(), R.layout.list_item, null);
                        holder = new ViewHolder();
                        holder.ivImage = (ImageView) convertView.findViewById(R.id.iv_image);
                        convertView.setTag(holder);
                    } else {
                        holder = (ViewHolder) convertView.getTag();
                    }
                    bitmap = mMemoryCacheUtils.getMemoryCache(list.get(position));
                    if (bitmap != null) {
                        // 从内存获取
                        holder.ivImage.setImageBitmap(bitmap);// 更新UI
                    } else {
                        // 若没有的话则开启新线程加载图片
                        queuePhoto(list.get(position), holder.ivImage);
    
                        // 设置默认图片
                        holder.ivImage.setImageResource(R.drawable.ic_launcher);
                    }
                    return convertView;
                }
        private void queuePhoto(String url, ImageView imageView) {
            PhotoToLoad p = new PhotoToLoad(url, imageView);//先保存住url和imageview
            executorService.submit(new PhotosLoader(p));//然后再开启子线程
        }
    
        // Task for the queue
        private class PhotoToLoad {
            public String url;
            public ImageView imageView;
    
            public PhotoToLoad(String u, ImageView i) {
                url = u;
                imageView = i;
            }
        }

    完整代码可以看LazyAdapter.java

    demo(lazylist)代码:https://pan.baidu.com/s/1mhZbaHi

  • 相关阅读:
    Lua_第 20 章 IO库
    maven具体解释之坐标与依赖
    用python做自己主动化測试--对Java代码做单元測试 (1)
    OSG粒子系统应用:雨雪效果
    Snort:Barnyard2+MySQL+BASE 基于Ubuntu 14.04SNORT
    shiro高速入门
    解决Cocos项目中遇到的fatal error c1083(无法打开包含文件)
    解决TIME_WAIT过多造成的问题
    Web后端语言模拟http请求(带username和password)实例代码大全
    Python
  • 原文地址:https://www.cnblogs.com/johnsonwei/p/5935885.html
Copyright © 2011-2022 走看看