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.
精彩评论