开发者

android: caching drawable elements for performance

I'm trying to cache Drawable objects that are included in a listview:

I have the following inside the Adapter:

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;
        }       

    }

And the class ImageThreadLoad is as the following:

public class ImageThreadloader  {


    public void loadImage(String imageurl,ImageView imageview) 
    {
            开发者_JAVA技巧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);
                }
            }



        }
    }
}

Works perfectly but it has some delay if I scroll the listview quickly. I have read several tutorials and the solution is always the same: to cache.

SO I have tried the following (changing the class that load the image in a separate thread):

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);
        }
    }

Every seems to work fine but when i scroll images start to disapperar in some rows. Something wrong? Any tool to help me to solve this issues?

Thanks in advance


To start with, lets look at this code.

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

The point of the SoftReference is that the system may collect the contained reference. In that case the drawable.get() will return null and your image will disappear.

Also check out ignition - Either for inspiration or for use.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜