android:缓存可绘制元素以提高性能

时间:2011-02-21 16:11:52

标签: android image caching listview

我正在尝试缓存listview中包含的Drawable对象:

我在适配器中有以下内容:

private final ImageThreadloader imageloader=new ImageThreadloader();

public View getView(int position, View convertView, ViewGroup parent)
    {
        View row=convertView;
        ViewWrapper wrapper=null;
        Activity activity=(Activity)getContext();

        RssItem item=getItem(position);

        if (row == null) {

            LayoutInflater inflater=activity.getLayoutInflater();
            row=inflater.inflate(R.layout.row,null);
            wrapper=new ViewWrapper(row);
            row.setTag(wrapper);
        }
        else
        {
            wrapper=(ViewWrapper)row.getTag();
        }

        wrapper.getTitle().setText(item.getTitle());
        String cleaned=item.getDescription().replaceAll("\\<.*?\\>", "");
        int Long=cleaned.length();
        if (Long<=100)
        {
            wrapper.getDescription().setText(cleaned);
        }
        else wrapper.getDescription().setText(cleaned.substring(0, 50)+"...");

        String laurl=item.getImageUrl();

        if (laurl!="") 
        { 
            imageloader.loadImage(laurl, (ImageView)wrapper.getImage());
        }
        else 
        {
            wrapper.getImage().setImageResource(R.drawable.icon);
        }

        return row;

    }

    static class ViewWrapper {

        private View base;
        private TextView title=null;
        private TextView description=null;
        private ImageView icono=null;

        ViewWrapper (View base) {
            this.base=base;
        }

        public TextView getTitle() {
            if (title==null) {
                title=(TextView)base.findViewById(R.id.TitleText);
            }
            return title;
        }

        public TextView getDescription() {
            if (description==null) {
                description=(TextView)base.findViewById(R.id.DescriptionText);
            }
            return description;
        }

        public ImageView getImage() {
            if (icono==null) {
                icono=(ImageView)base.findViewById(R.id.ImageIcon);
            }
            return icono;
        }       

    }

类ImageThreadLoad如下:

public class ImageThreadloader  {


    public void loadImage(String imageurl,ImageView imageview) 
    {
            DrawableDownLoaderTask imagetask= new DrawableDownLoaderTask(imageview);            
            imagetask.execute(imageurl);
    }


    public static Drawable loadImageFromUrl(String url) {
        InputStream inputStream;
        try {
            inputStream = new URL(url).openStream();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        return Drawable.createFromStream(inputStream, "src");
    }

    class DrawableDownLoaderTask extends AsyncTask<String, Void, Drawable> {

        private String url;
        private final WeakReference<ImageView> imageviewreference;      

        public DrawableDownLoaderTask(ImageView imageview) {
            imageviewreference=new WeakReference<ImageView>(imageview);
        }

        @Override
        protected Drawable doInBackground(String... params)
        {
            url=params[0];
            Drawable drawable=loadImageFromUrl(url);
            return drawable;

        }

        @Override
        protected void onPostExecute(Drawable drawable)
        {

            if (isCancelled()) 
            {
                drawable=null;
            }

            if (imageviewreference!=null)
            {
                ImageView imageview=imageviewreference.get();
                if (imageview!=null)
                {
                    imageview.setImageDrawable(drawable);
                }
            }



        }
    }
}

完美无缺,但如果我快速滚动列表视图会有一些延迟。我已经阅读了几个教程,解决方案总是一样的:缓存。

所以我尝试了以下内容(更改在单独的线程中加载图像的类):

private final HashMap <String, SoftReference <Drawable>> imagecache= new HashMap <String, SoftReference<Drawable>>();

    public void loadImage(String imageurl,ImageView imageview) 
    {
        if (imagecache.containsKey(imageurl))
        {
            SoftReference<Drawable> drawable= imagecache.get(imageurl);
            imageview.setImageDrawable(drawable.get());
        }
        else
        {   
            DrawableDownLoaderTask imagetask= new DrawableDownLoaderTask(imageview);
            imagetask.execute(imageurl);
        }

    }
    class DrawableDownLoaderTask extends AsyncTask<String, Void, Drawable> {

        private String url;
        private final WeakReference<ImageView> imageviewreference;      

        public DrawableDownLoaderTask(ImageView imageview) {
            imageviewreference=new WeakReference<ImageView>(imageview);
        }

        @Override
        protected Drawable doInBackground(String... params)
        {
            url=params[0];
            Drawable drawable=loadImageFromUrl(url);
            if (drawable!=null) imagecache.put(url, new SoftReference<Drawable>(drawable));
            return drawable;

        }

        @Override
        protected void onPostExecute(Drawable drawable)
        {
            ImageView imageview=imageviewreference.get();
            imageview.setImageDrawable(drawable);
        }
    }

每一个似乎工作正常,但当我滚动图像开始消失在某些行。 有问题? 有什么工具可以帮我解决这个问题吗?

提前致谢

1 个答案:

答案 0 :(得分:0)

首先,让我们看看这段代码。

SoftReference<Drawable> drawable= imagecache.get(imageurl);
imageview.setImageDrawable(drawable.get());

SoftReference的要点是系统可能会收集包含的引用。在这种情况下,drawable.get()将返回null,您的图片将会消失。

同时查看ignition - 无论是灵感还是使用。