将图像在后台加载到列表视图时出现内存不足错误

时间:2014-08-08 16:53:57

标签: android android-listview bitmap android-asynctask

我正在尝试使用列表视图上的自定义适配器从网址加载图片。我收到内存不足错误。我正在使用下面链接中的代码

http://android-developers.blogspot.com/2010/07/multithreading-for-performance.html

package com.example.video;

import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.ref.WeakReference;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.methods.HttpGet;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.net.http.AndroidHttpClient;
import android.os.AsyncTask;
import android.util.Log;
import android.widget.ImageView;

class BitmapDownloaderTask extends AsyncTask<String, Void, Bitmap> {
    String url;
    private final WeakReference<ImageView> imageViewReference;

    public BitmapDownloaderTask(ImageView imageView) {
        imageViewReference = new WeakReference<ImageView>(imageView);
    }

    @Override
    // Actual download method, run in the task thread
    protected Bitmap doInBackground(String... params) {
         // params comes from the execute() call: params[0] is the url.
        url=params[0];
         return downloadBitmap(url);
    }

    @Override
    // Once the image is downloaded, associates it to the imageView
    protected void onPostExecute(Bitmap bitmap) {
        if (imageViewReference != null) {
            ImageView imageView = imageViewReference.get();
            BitmapDownloaderTask bitmapDownloaderTask = getBitmapDownloaderTask(imageView);
            // Change bitmap only if this process is still associated with it
            if (this == bitmapDownloaderTask) {
                imageView.setImageBitmap(bitmap);
            }
        }
    }

    private static BitmapDownloaderTask getBitmapDownloaderTask(ImageView imageView) {
        if (imageView != null) {
            Drawable drawable = imageView.getDrawable();
            if (drawable instanceof DownloadedDrawable) {
                DownloadedDrawable downloadedDrawable = (DownloadedDrawable)drawable;
                return downloadedDrawable.getBitmapDownloaderTask();
            }
        }
        return null;
    }
    static class DownloadedDrawable extends ColorDrawable {
        private final WeakReference<BitmapDownloaderTask> bitmapDownloaderTaskReference;

        public DownloadedDrawable(BitmapDownloaderTask bitmapDownloaderTask) {
            super(Color.BLACK);
            bitmapDownloaderTaskReference =
                new WeakReference<BitmapDownloaderTask>(bitmapDownloaderTask);
        }

        public BitmapDownloaderTask getBitmapDownloaderTask() {
            return bitmapDownloaderTaskReference.get();
        }
    }

    static Bitmap downloadBitmap(String url) {
        final AndroidHttpClient client = AndroidHttpClient.newInstance("Android");
        final HttpGet getRequest = new HttpGet(url);

        try {
            HttpResponse response = client.execute(getRequest);
            final int statusCode = response.getStatusLine().getStatusCode();
            if (statusCode != HttpStatus.SC_OK) { 
                Log.w("ImageDownloader", "Error " + statusCode + " while retrieving bitmap from " + url); 
                return null;
            }

            final HttpEntity entity = response.getEntity();
            if (entity != null) {
                InputStream inputStream = null;
                try {
                    inputStream = entity.getContent(); 
                    final Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
                    return bitmap;
                } finally {
                    if (inputStream != null) {
                        inputStream.close();  
                    }
                    entity.consumeContent();
                }
            }
        } catch (Exception e) {
            // Could provide a more explicit error message for IOException or IllegalStateException
            getRequest.abort();
            Log.d("ImageDownloader", "Error while retrieving bitmap from "+url+""+e.toString());
        } finally {
            if (client != null) {
                client.close();
            }
        }
        return null;
    }
    static class FlushedInputStream extends FilterInputStream {
        public FlushedInputStream(InputStream inputStream) {
            super(inputStream);
        }

        @Override
        public long skip(long n) throws IOException {
            long totalBytesSkipped = 0L;
            while (totalBytesSkipped < n) {
                long bytesSkipped = in.skip(n - totalBytesSkipped);
                if (bytesSkipped == 0L) {
                      int byt = read();
                      if (byt < 0) {
                          break;  // we reached EOF
                      } else {
                          bytesSkipped = 1; // we read one byte
                      }
               }
                totalBytesSkipped += bytesSkipped;
            }
            return totalBytesSkipped;
        }
    }
}

我的自定义适配器:

package com.example.video;

import java.util.ArrayList;

import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.drawable.Drawable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.TextView;

import com.example.records.MyRecord;
import com.example.video.BitmapDownloaderTask.DownloadedDrawable;


//Showing all the text and images on a list view
 public class CustomAdapter extends ArrayAdapter{
  int size=1;
  Context context;
  ArrayList<MyRecord> Name;
  Bitmap bitmap;
  Activity a;
  Bitmap mPlaceHolderBitmap;
  public CustomAdapter(Context c, ArrayList<MyRecord> Name,Activity a) {
      super(c, R.layout.list_row,Name);
      this.context=c;
      this.Name=Name;
      this.a=a;
  }
  public View getView(int position, View convertView, ViewGroup parent){

      LayoutInflater inflater=(LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
      View row=inflater.inflate(R.layout.list_row, parent,false);

      TextView title=(TextView) row.findViewById(R.id.textView1);
      title.setText(""+Name.get(position).getTitle());
      title.setTypeface(Splash.tf);

      TextView author=(TextView) row.findViewById(R.id.textAuthor);
      author.setText(""+Name.get(position).getTitle());
      author.setTypeface(Splash.tf);

      TextView views=(TextView) row.findViewById(R.id.textViews);
      views.setText(""+Name.get(position).getViews()+"views");
      views.setTypeface(Splash.tf);

      TextView date=(TextView) row.findViewById(R.id.textDatePublished);
      date.setText(""+Name.get(position).getDate_Published());
      date.setTypeface(Splash.tf);

      ImageView i=(ImageView) row.findViewById(R.id.imageview1);
      String url=Name.get(position).getImgUri();
      String imageUrl="http://64.111.243.324/vod/"+url;
//      i.setTag(imageUrl);



      //running an asynchronous task in the background to load images from url
//     new MyTask().execute(i);

      ImageDownloader id=new ImageDownloader();
      id.download(imageUrl, i);
      return row;
    }
}

Image Downloader Class:

package com.example.video;

import com.example.video.BitmapDownloaderTask.DownloadedDrawable;

import android.graphics.drawable.Drawable;
import android.widget.ImageView;

public class ImageDownloader {

    public void download(String url, ImageView imageView) {
         if (cancelPotentialDownload(url, imageView)) {
             BitmapDownloaderTask task = new BitmapDownloaderTask(imageView);
             DownloadedDrawable downloadedDrawable = new DownloadedDrawable(task);
             imageView.setImageDrawable(downloadedDrawable);
             task.execute(url);
         }
    }
    private static boolean cancelPotentialDownload(String url, ImageView imageView) {
        BitmapDownloaderTask bitmapDownloaderTask = getBitmapDownloaderTask(imageView);

        if (bitmapDownloaderTask != null) {
            String bitmapUrl = bitmapDownloaderTask.url;
            if ((bitmapUrl == null) || (!bitmapUrl.equals(url))) {
                bitmapDownloaderTask.cancel(true);
            } else {
                // The same URL is already being downloaded.
                return false;
            }
        }
        return true;
    }
    private static BitmapDownloaderTask getBitmapDownloaderTask(ImageView imageView) {
        if (imageView != null) {
            Drawable drawable = imageView.getDrawable();
            if (drawable instanceof DownloadedDrawable) {
                DownloadedDrawable downloadedDrawable = (DownloadedDrawable)drawable;
                return downloadedDrawable.getBitmapDownloaderTask();
            }
        }
        return null;
    }
    }

2 个答案:

答案 0 :(得分:0)

删除AsyncTask并从适配器使用picasso api http://square.github.io/picasso

答案 1 :(得分:0)

如果不使用'convertView'参数,你会过多地夸大视图,这也可能导致性能问题。通过执行以下操作解决此问题:

View row = convertView != null ? convertView : inflater.inflate(R.layout.list_row, parent,false);

关于图像缓存,请不要重新发明轮子,而是专注于应用程序的核心逻辑。只需使用已知且可靠的Cache&amp; amp;框架。获取图像,例如Picasso

您的代码将被缩减,在您的getView()方法中,您只需使用它:

Picasso.with(context).load("http://i.imgur.com/DvpvklR.png").into(imageView);