2

我不確定如何回收位圖。Android中的位圖回收 - 何時何地?

我有一個應用程序,在列表視圖中顯示大量的項目。問題是,如果我不降低ImageDownloader類中圖像的質量,應用程序會崩潰。

在下面提供的代碼中,如果我更改options.inSampleSize = 4,圖像的質量會降低,並且應用程序不會耗盡內存。但是,我想使用高品質的圖像,而不會崩潰我的應用程序。

我該怎麼做?我ImageDownloader的

部分:

static Bitmap downloadBitmap(String url) { 
    HttpParams params = new BasicHttpParams(); 
    params.setParameter(CoreProtocolPNames.PROTOCOL_VERSION, HttpVersion.HTTP_1_1); 
    HttpClient client = new DefaultHttpClient(params); 
    final HttpGet getRequest = new HttpGet(url); 

    try { 
     HttpResponse response = client.execute(getRequest); 
     final int statusCode = response.getStatusLine().getStatusCode(); 
     if (statusCode != HttpStatus.SC_OK) { 
      String[] urlBits = url.split("/"); 
      Bitmap bitmap = MiscHelpers.getBitmapFromAsset(context, "animals/" + urlBits[urlBits.length-2] + ".jpg"); 
      Log.w("ImageDownloader", "Error " + statusCode + " while retrieving bitmap from " + url); 
      return bitmap; 
     } 

     final HttpEntity entity = response.getEntity(); 
     if (entity != null) { 
      InputStream inputStream = null; 
      try { 
       inputStream = entity.getContent(); 
       BitmapFactory.Options options=new BitmapFactory.Options(); 
       options.inSampleSize = 1; 


       final Bitmap bitmap = BitmapFactory.decodeStream(inputStream,null,options); 
       //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.w("ImageDownloader", "Error while retrieving bitmap from " + url + e.toString()); 
    } finally { 
     if (client != null) { 
      //client.close(); 
     } 
    } 
    return null; 
} 

我的ListView適配器:

@Override 
public View getView(int position, View convertView, ViewGroup parent) { 

    // Inflate the layout 
    LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
    View rowView = inflater.inflate(R.layout.list_single, parent, false); 

    ImageView image = (ImageView) rowView.findViewById(R.id.picture); 
    TextView firstline = (TextView) rowView.findViewById(R.id.firstline); 
    TextView secondline = (TextView) rowView.findViewById(R.id.secondline);   

    // Get information about the report 
    AnimalLocationLog current = objects.get(position); 

    // Get all the important information 
    String species = current.getSpecies(); 
    String sanitizedSpecies = MiscHelpers.sanitizeString(species); 
    int reportId = objects.get(position).getTrackerId(); 

    // Construct the URL to the image 
    String imageLocation = websiteUrl + sanitizedSpecies + separator + reportId + extension; 

    // Display user report   
    downloader.download(imageLocation, image);   
    firstline.setText(species); 
    secondline.setText("Spotted " + current.getDateTime().toString("yyyy-MM-dd H:m"));   

    urlToPath = downloader.getUrlToPath(); 

    return rowView; 
} 
+0

使用ViewHolder模式是一種很好的做法。另外,您應該在後臺加載圖像(downloader.download方法)。然後,您可以修改此方法以接收imageView,並且可以在設置新圖像之前回收以前的位圖。它值得閱讀:http://developer.android.com/training/displaying-bitmaps/load-bitmap.html(如果你沒有它)。 –

回答

1

我看不出有什麼錯得離譜。也許在圖像編輯方面可以做些什麼來使圖像更小?

我會建議將堆轉儲並將其加載到Eclipse MAT,https://www.eclipse.org/mat/中,以獲取正在發生的事情的完整畫面。特別是我會建議看看支配者報告。

+0

嗨馬特,謝謝你的回答。我可以使圖像變小,但是,我仍然需要回收位圖,不是嗎? – chuckfinley

+0

我不確定它需要回收位圖。根據本指南,回收僅針對Gingerbread和更低版本提供,https://developer.android.com/training/displaying-bitmaps/manage-memory.html#recycle。如果你想嘗試回收位圖,你應該遵循該文章中的建議「只有當你確定位圖不再被使用時,你才應該使用recycle()。如果你調用recycle()並且稍後嘗試繪製位圖,你會得到錯誤:「畫布:試圖使用回收的位圖」。「 –