• android listview 异步加载问题



    ====================问题描述====================
    学做android,自己想模仿QQ空间做一个小demo
    listview异步加载图片的时候遇到了一个问题
    异步加载用到了SoftReference 和文件缓存的方法
    每次加载图片的时候,也在内存或缓存中找到了图片
    第一次加载出来后,listview滑动了,同样也进到了setImageBitmap这一步
    可是就是图片显示不出来变成空白
    下面帖几张图和代码
    滑动前

    滑动后
    Image_url = new StringBuffer(AppConstant.DOWNLOAD_IMAGE_URL)
    .append(msg.getOPImageList().get(0).getImageUrl())
    .toString();
    
    ImageView imageView = holder.msgImage;
    imageView.setTag(Image_url);
    Bitmap bitmap = Loader.loadBitmap(imageView, Image_url,
    new ImageCallBack() {
    @Override
    public void imageLoad(ImageView imageView, Bitmap bitmap) {
    if (imageView.getTag() != null
    && imageView.getTag().equals(Image_url)) {
    imageView.setImageBitmap(bitmap);
    }
    }
    });
    Log.e("当前的postion", "" + position);
    if (bitmap == null) {
    imageView.setImageDrawable(context.getResources().getDrawable(
    R.drawable.ic_launcher));
    } else {
    imageView.setImageBitmap(bitmap);
    }

    loader
    public class Loader {
    /**
     * 内存图片软引用缓冲
     */
    private static HashMap<String, SoftReference<Bitmap>> imageCache = null;
    
    public Loader() {
    imageCache = new HashMap<String, SoftReference<Bitmap>>();
    }
    
    public static String getFileName(String url) {
    return url.substring(url.lastIndexOf(File.separator) + 1);
    }
    
    public static Bitmap getLocalResource(String destDir, String imageName) {
    
    Bitmap bmp = null;
    File imgeDir = new File(destDir);
    File cache = null;
    if (!imgeDir.exists()) { // 判断本地缓存目录是否存在
    imgeDir.mkdirs();
    } else {
    cache = new File(destDir + File.separator + imageName); // 判断该图片资源是否存在
    
    if (cache.exists()) { // 如果存在就根据图片的存储路径得到Bitmap对象 bm
    
    bmp = BitmapFactory.decodeFile(cache.getAbsolutePath());
    }
    }
    return bmp;
    }
    
    public static Bitmap loadBitmap(final ImageView imageView, final String imageURL,
    final ImageCallBack imageCallBack) {
    // 在内存缓存中,则返回Bitmap对象
    if (imageCache.containsKey(imageURL)) {
    SoftReference<Bitmap> reference = imageCache.get(imageURL);
    Bitmap bitmap = reference.get();
    if (bitmap != null) {
    return bitmap;
    }
    } else {
    /**
     * 加上一个对本地缓存的查找
     */
    String bitmapName = imageURL
    .substring(imageURL.lastIndexOf("/") + 1);
    Bitmap bitmapTemp = null;
    bitmapTemp = getLocalResource(AppConstant.TEST, bitmapName);
    if (bitmapTemp != null) {
    return bitmapTemp;
    }
    }
    
    final Handler handler = new Handler() {
    /*
     * (non-Javadoc)
     * 
     * @see android.os.Handler#handleMessage(android.os.Message)
     */
    @Override
    public void handleMessage(Message msg) {
    // TODO Auto-generated method stub
    imageCallBack.imageLoad(imageView, (Bitmap) msg.obj);
    }
    };
    
    // 如果不在内存缓存中,也不在本地(被jvm回收掉),则开启线程下载图片
    new Thread() {
    /*
     * (non-Javadoc)
     * 
     * @see java.lang.Thread#run()
     */
    @Override
    public void run() {
    // TODO Auto-generated method stub
    Bitmap bitmap = null;
    try {
    
    URL imageUrl = new URL(imageURL);
    HttpURLConnection conn =  (HttpURLConnection) imageUrl
    .openConnection();
    conn.setConnectTimeout(30000);
    conn.setReadTimeout(30000);
    conn.setInstanceFollowRedirects(true);
    // InputStream is = conn.getInputStream();
    
    InputStream in = conn.getInputStream();
    BitmapFactory.Options options = new BitmapFactory.Options();
    options.inJustDecodeBounds = false;
    options.inSampleSize = 10; // width,hight设为原来的十分一
    bitmap = BitmapFactory.decodeStream(in, null, options);
    } catch (MalformedURLException e1) {
    // TODO Auto-generated catch block
    e1.printStackTrace();
    } catch (IOException e1) {
    // TODO Auto-generated catch block
    e1.printStackTrace();
    }
    
    imageCache.put(imageURL, new SoftReference<Bitmap>(bitmap));
    Message msg = handler.obtainMessage(0, bitmap);
    handler.sendMessage(msg);
    
    File dir = new File(AppConstant.TEST);
    if (!dir.exists()) {
    dir.mkdirs();
    }
    
    File bitmapFile = new File(AppConstant.TEST + File.separator
    + imageURL.substring(imageURL.lastIndexOf("/") + 1));
    if (!bitmapFile.exists()) {
    try {
    bitmapFile.createNewFile();
    } catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }
    }
    FileOutputStream fos;
    try {
    fos = new FileOutputStream(bitmapFile);
    bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos);
    fos.close();
    } catch (FileNotFoundException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    } catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }
    }
    }.start();
    
    return null;
    }
    
    /**
     * 回调接口
     * 
     * @author onerain
     * 
     */
    public interface ImageCallBack {
    public void imageLoad(ImageView imageView, Bitmap bitmap);
    }
    }

    坐等大神支招啊
    每次都进了setimagebitmap这一步 就是加载不出图片


    ====================解决方案1====================
    你用imageLoader这个三方开源库试试。
    ====================解决方案2====================
    看一下你imageview控件设的是src还是background。或者试试把bitmap转成drawable,再setbackground试试
    ====================解决方案3====================
    看下getView方法?
    ====================解决方案4====================
    贴下Adapter的代码看看呗
    ====================解决方案5====================
    你试试AsyncImage这个第三方开源库
    ====================解决方案6====================
      ImageView imageViewByTag = (ImageView) listview 
                                    .findViewWithTag(imageUrl); 

    问题应该在这一句 你这个搜索 只会找到第一个TAG 是imageUrl的控件。 可能并不是你的要更新的控件。

    比如  你setTAG了  , listView 会重用item的,   在 msg.getOPImageList().size()=0 时候 还是有这个tag。  
    然后你find的结果就是这个contentView里面的,不是你要更新的那个ImageView。 
    ====================解决方案7====================
    引用
    Image_url = new StringBuffer(AppConstant.DOWNLOAD_IMAGE_URL)
    .append(msg.getOPImageList().get(0).getImageUrl())
    .toString();

    ImageView imageView = holder.msgImage;
    imageView.setTag(Image_url);
    Bitmap bitmap = Loader.loadBitmap(imageView, Image_url,
    new ImageCallBack() {
    @Override
    public void imageLoad(ImageView imageView, Bitmap bitmap) {
    if (imageView.getTag() != null
    && imageView.getTag().equals(Image_url)) {
    imageView.setImageBitmap(bitmap);
    }
    }
    });
    Log.e("当前的postion", "" + position);
    if (bitmap == null) {
    imageView.setImageDrawable(context.getResources().getDrawable(
    R.drawable.ic_launcher));
    } else {
    imageView.setImageBitmap(bitmap);
    }



    这个代码中  在 ImageCallBack 接口中 吧imageUrl 回传回来,跟imageView.getTag() 进行比较,应该可以解决问题。试试看。
  • 相关阅读:
    测试VPS
    [转] 如何在vps上安装和登录Xwindows
    [转]设置修改CentOS系统时区
    顺序队列
    求二叉树的高度
    VMware Workstation cannot connect to the virtual machine
    如何查看hadoop是32位还是64位
    64位CentOS上编译 Hadoop 2.2.0
    hadoop 2.X下eclipse配置
    删除文件及文件夹
  • 原文地址:https://www.cnblogs.com/lianxu61/p/4002195.html
Copyright © 2020-2023  润新知