【问题标题】:Lru Cache listView image issuesLru Cache listView 图片问题
【发布时间】:2012-12-05 03:07:50
【问题描述】:

我的 ListView 在我的活动中包含图像,在我添加 LRU 缓存之前效果很好。当我第一次加载时(如果我不滚动它),而图像正在加载,第一个元素会在我正在加载的所有图像之间更改其图像。

我的 LRU 缓存看起来像

public class Image {
    private static LruCache<String, Bitmap>     mMemoryCache    = null;
    private static int                          cacheSize       = 1024 * 1024 * 10;

    private static class AsyncLoader extends AsyncTask<String, Void, Bitmap> {
        private ImageView   mTarget;

        public AsyncLoader(ImageView target) {
            this.mTarget = target;
        }

        @Override
        protected void onPreExecute() {
            mTarget.setTag(this);
        }

        @Override
        protected Bitmap doInBackground(String...urls) {
            String url = urls[0];

            Bitmap result = null;

            if (url != null) {
                result = load(url);

                if (result != null) {
                    mMemoryCache.put(url, result);
                }
            }

            return result;
        }

        @Override
        protected void onPostExecute(Bitmap result) {
            if (mTarget.getTag() == this) {
                mTarget.setTag(null);
                if (result != null) mTarget.setImageBitmap(result);
            }
        }
    }

    public static Bitmap load(String urlString) {
        if (urlString == null || urlString.length() == 0) return null;

        Bitmap bitmap = null;
        URL url = null;

        try {
            url = new URL(urlString);
        } catch (MalformedURLException e) {
            e.printStackTrace();
        }

        try {
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setDoInput(true);
            conn.connect();
            InputStream is = conn.getInputStream();
            bitmap = BitmapFactory.decodeStream(is);
            is.close();
        } catch (IOException e) {
            e.printStackTrace();
        }

        return bitmap;
    }

    public static void loadToView(String url, ImageView view) {
        if (url == null || url.length() == 0) return;
        if (mMemoryCache == null) {
            mMemoryCache = new LruCache<String, Bitmap>(cacheSize) {
                @Override
                protected int sizeOf(String key, Bitmap bitmap) {
                    return (bitmap.getRowBytes() * bitmap.getHeight());
                }
            };
        }

        Bitmap bitmap = getBitmapFromMemCache(url);
        if (bitmap == null) {
            final AsyncLoader task = (AsyncLoader) new AsyncLoader(view);
            view.setTag(task);
            task.execute(url);
        } else {
            view.setImageBitmap(bitmap);
        }
    }
}

用法:

Image.loadToView("http://image_url", (ImageView) view.findViewById(R.id.img_thumbnail));

这就是我的 BaseAdapter getView 的样子

@Override
public View getView(final int position, View view, ViewGroup parent) {
    if (view == null) view = inflater.inflate(R.layout.list_item, null);

    ((TextView) view.findViewById(R.id.txt_name)).setText(filtered_data.get(position).name);

    Image.loadToView("http://graph.facebook.com/" + filtered_data.get(position).id + "/picture", (ImageView) view.findViewById(R.id.img_thumbnail));

    return view;
}

【问题讨论】:

  • 在 imageview 下载时尝试设置 null
  • 但是如果不存在我想要一个默认图像?无论如何我都会尝试这个......
  • 你能显示来自适配器的getView 方法吗?
  • 已更新,我只是使用静态方法来设置图像 url 和视图,如果我在没有 Lru 缓存的情况下加载它就可以正常工作..
  • 您的 getView 方法不是很有效。您最好从参数中返回视图。

标签: java android android-lru-cache


【解决方案1】:

我发现阅读了很多关于 listview 问题的图片,它与 listview 回收有关,一些相关的帖子:

我添加的是 onPostExecute 方法中的 else 语句,如果标签不是设置在标签上的那个我取消它。

它的固定代码

public class Image {
    private static LruCache<String, Bitmap>     mMemoryCache    = null;
    private static int                          cacheSize       = 1024 * 1024 * 10;

    private static class AsyncLoader extends AsyncTask<String, Void, Bitmap> {
        private ImageView   mTarget;

        public AsyncLoader(ImageView target) {
            this.mTarget = target;
        }

        @Override
        protected void onPreExecute() {
            mTarget.setTag(this);
        }

        @Override
        protected Bitmap doInBackground(String...urls) {
            String url = urls[0];

            Bitmap result = null;

            if (url != null) {
                result = load(url);

                if (result != null) {
                    mMemoryCache.put(url, result);
                }
            }

            return result;
        }

        @Override
        protected void onPostExecute(Bitmap result) {
            if (mTarget.getTag() == this) {
                mTarget.setTag(null);
                if (result != null) mTarget.setImageBitmap(result);
            } else if (mTarget.getTag() != null) {
                ((AsyncLoader) mTarget.getTag()).cancel(true);
                mTarget.setTag(null);
            }
        }
    }

    public static Bitmap load(String urlString) {
        if (urlString == null || urlString.length() == 0) return null;

        Bitmap bitmap = null;
        URL url = null;

        try {
            url = new URL(urlString);
        } catch (MalformedURLException e) {
            e.printStackTrace();
        }

        try {
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setDoInput(true);
            conn.connect();
            InputStream is = conn.getInputStream();
            bitmap = BitmapFactory.decodeStream(is);
            is.close();
        } catch (IOException e) {
            e.printStackTrace();
        }

        return bitmap;
    }

    public static void loadToView(String url, ImageView view) {
        if (url == null || url.length() == 0) return;
        if (mMemoryCache == null) {
            mMemoryCache = new LruCache<String, Bitmap>(cacheSize) {
                @Override
                protected int sizeOf(String key, Bitmap bitmap) {
                    return (bitmap.getRowBytes() * bitmap.getHeight());
                }
            };
        }

        Bitmap bitmap = getBitmapFromMemCache(url);
        if (bitmap == null) {
            final AsyncLoader task = (AsyncLoader) new AsyncLoader(view);
            view.setTag(task);
            task.execute(url);
        } else {
            view.setImageBitmap(bitmap);
        }
    }
}

我认为 google 需要解决此问题或提供更简洁的解决方法,因为(在我看来)google 在构建某些东西时失败,开发人员只需要关心构建自己的应用程序而不是浪费时间寻找方法解决sdk问题

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多