Android: кэширование рисованных элементов для производительности - PullRequest
5 голосов
/ 21 февраля 2011

Я пытаюсь кэшировать 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 голосов
/ 21 февраля 2011

Для начала давайте посмотрим на этот код.

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

Смысл SoftReference в том, что система может собирать содержащиеся ссылки.В этом случае drawable.get() вернет null и ваше изображение исчезнет.

Также проверьте зажигание - либо для вдохновения, либо для использования.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...