2016-12-02 16 views
0

複数のアクティビティを再読み込みした後に問題が発生しました。メモリ不足例外が発生し、アプリがクラッシュしました。開発者のGoogleドキュメントの例を使用して、私はそれを行っていますが、私は、複数のビットマップを持って考慮し、ここでは外部のクラスから複数のリロード後にAndroid out of memoryエラーが発生する

をビットマップを呼び出して、これを行うためには、私のロードマップクラスは

public class bitmapHTTP{ 

Context ctx; 
private LruCache<String, Bitmap> mMemoryCache; 
int iv; 

public bitmapHTTP(Context c){ 
    ctx = c; 
    final int maxMemory = (int) (Runtime.getRuntime().maxMemory()/1024); 
    final int cacheSize = maxMemory/8; 

    mMemoryCache = new LruCache<String, Bitmap>(cacheSize) { 
     @Override 
     protected int sizeOf(String key, Bitmap bitmap) { 
      // The cache size will be measured in kilobytes rather than 
      // number of items. 
      return bitmap.getByteCount()/1024; 
     } 
    }; 

} 

public void addBitmapToMemoryCache(String key, Bitmap bitmap) { 
    if(getBitmapFromMemCache(key) == null) { 
     mMemoryCache.put(key, bitmap); 
    } 
} 

public Bitmap getBitmapFromMemCache(String key) { 
    return mMemoryCache.get(key); 
} 

public void loadBitmap(String resId, ImageView imageView) { 
    final String imageKey = String.valueOf(resId); 
    iv = imageView.getWidth(); 
    Bitmap bitmap = getBitmapFromMemCache(imageKey); 
    if(bitmap != null) { 
     imageView.setImageBitmap(bitmap); 
    }else{ 
     if(cancelPotentialWork(imageKey, imageView)){ 
      Bitmap loading = decodeSampledBitmapFromResource(ctx.getResources(), R.drawable.whiteseetrough, imageView.getWidth(), imageView.getWidth()); 
      BitmapWorkerTask task = new BitmapWorkerTask(imageView); 
      AsyncDrawable asyncDrawable = new AsyncDrawable(ctx.getResources(), loading, task); 
      imageView.setImageDrawable(asyncDrawable); 
      task.execute(resId); 
     } 
    } 
} 

public static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) { 
    // Raw height and width of image 
    final int height = options.outHeight; 
    final int width = options.outWidth; 
    int inSampleSize = 1; 

    if (height > reqHeight || width > reqWidth) { 

     final int halfHeight = height/2; 
     final int halfWidth = width/2; 

     // Calculate the largest inSampleSize value that is a power of 2 and keeps both 
     // height and width larger than the requested height and width. 
     while ((halfHeight/inSampleSize) > reqHeight 
       && (halfWidth/inSampleSize) > reqWidth) { 
      inSampleSize *= 2; 
     } 
    } 

    return inSampleSize; 
} 

public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId, int reqWidth, int reqHeight) { 

    // First decode with inJustDecodeBounds=true to check dimensions 
    final BitmapFactory.Options options = new BitmapFactory.Options(); 
    options.inJustDecodeBounds = true; 
    BitmapFactory.decodeResource(res, resId, options); 

    // Calculate inSampleSize 
    options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight); 

    // Decode bitmap with inSampleSize set 
    options.inJustDecodeBounds = false; 
    return BitmapFactory.decodeResource(res, resId, options); 
} 

class BitmapWorkerTask extends AsyncTask<String, Void, Bitmap> { 
    private final WeakReference<ImageView> imageViewReference; 
    private String data = null; 

    public BitmapWorkerTask(ImageView imageView) { 
     // Use a WeakReference to ensure the ImageView can be garbage collected 
     imageViewReference = new WeakReference<ImageView>(imageView); 
    } 

    // Decode image in background. 
    @Override 
    protected Bitmap doInBackground(String... params) { 
     data = params[0]; 
     final BitmapFactory.Options options = new BitmapFactory.Options(); 
     Bitmap bitmap; 

     if(data.equals("null")){ 
      bitmap = decodeSampledBitmapFromResource(ctx.getResources(), R.drawable.whiteseetrough, iv, iv); 
      addBitmapToMemoryCache(String.valueOf(params[0]), bitmap); 
      return bitmap; 
     }else{ 
      bitmap = getBitmapFromMemCache(data); 
      if(bitmap == null){ 
       // Process as normal 
       try { 
        URL url = new URL(data); 
        HttpURLConnection connection = (HttpURLConnection) url.openConnection(); 
        connection.setDoInput(true); 
        connection.connect(); 
        InputStream input = connection.getInputStream(); 

        options.inSampleSize = calculateInSampleSize(options, iv, iv); 

        options.inJustDecodeBounds = false; 
        bitmap = BitmapFactory.decodeStream(input, null, options); 
        addBitmapToMemoryCache(String.valueOf(params[0]), bitmap); 
        return bitmap; 

       }catch(IOException e){ 
        e.printStackTrace(); 
        return null; 
       } 
      } 

     } 
     return bitmap; 
    } 

    // Once complete, see if ImageView is still around and set bitmap. 

    @Override 
    protected void onPostExecute(Bitmap bitmap) { 
     if (isCancelled()) { 
      bitmap = null; 
     } 

     if (imageViewReference != null && bitmap != null) { 
      final ImageView imageView = imageViewReference.get(); 
      final BitmapWorkerTask bitmapWorkerTask = 
        getBitmapWorkerTask(imageView); 
      if (this == bitmapWorkerTask && imageView != null) { 
       imageView.setImageBitmap(bitmap); 
      } 
     } 
    } 

} 

static class AsyncDrawable extends BitmapDrawable { 
    private final WeakReference<BitmapWorkerTask> bitmapWorkerTaskReference; 

    public AsyncDrawable(Resources res, Bitmap bitmap, 
         BitmapWorkerTask bitmapWorkerTask) { 
     super(res, bitmap); 
     bitmapWorkerTaskReference = 
       new WeakReference<BitmapWorkerTask>(bitmapWorkerTask); 
    } 

    public BitmapWorkerTask getBitmapWorkerTask() { 
     return bitmapWorkerTaskReference.get(); 
    } 
} 

public static boolean cancelPotentialWork(String data, ImageView imageView) { 
    final BitmapWorkerTask bitmapWorkerTask = getBitmapWorkerTask(imageView); 

    if (bitmapWorkerTask != null) { 
     final String bitmapData = bitmapWorkerTask.data; 
     // If bitmapData is not yet set or it differs from the new data 
     if(bitmapData == null || bitmapData != data) { 
      // Cancel previous task 
      bitmapWorkerTask.cancel(true); 
     } else { 
      // The same work is already in progress 
      return false; 
     } 
    } 
    // No task associated with the ImageView, or an existing task was cancelled 
    return true; 
} 

private static BitmapWorkerTask getBitmapWorkerTask(ImageView imageView) { 
    if (imageView != null) { 
     final Drawable drawable = imageView.getDrawable(); 
     if (drawable instanceof AsyncDrawable) { 
      final AsyncDrawable asyncDrawable = (AsyncDrawable) drawable; 
      return asyncDrawable.getBitmapWorkerTask(); 
     } 
    } 
    return null; 
} 

} 
ここで私は少しわからないよ一度ビットマップをリサイクルする必要が見ます

これは、ビットマップをimageViewにロードする方法です。

+0

私は、どこかでメモリリークがあると思います。 – Vyacheslav

+0

私のこの古い回答を確認してください。まだ適用されており、依然として非常に有効です。http://stackoverflow.com/questions/31162558/loading-images-in-a-gridview -from-server-android/31162942#31162942 – Budius

答えて

0

これは多くのコードです。すばやく私は尋ねる:それらを必要としなかった後にビットマップをリサイクルしていますか?ビットマップをリサイクルする必要があり、特にループなどでロードして参照を保持するときにRAMを解放する必要があります。

コードをチェックして、適切にリサイクルされていることを確認してください。私は種類の何かを見たことがなかった(ビットマップを低くしたい場合は参照を解放するだけでは不十分です)。

また、ビットマップが使用可能なメモリに正しくロードされ、メモリを消去しないようにサイズを変更する必要があることに注意してください。私はあなたがそこのどこかでそれをやっていると信じています。

+0

はいイメージが正しく読み込まれている問題は私がそれらをリサイクルする必要があるかどうか、メインクラスからリサイクルする方法がわからない – user2692997

+0

コードを怒らせてはいけませんここを見てみると、他の作業に進むのに役立つかもしれません。 https://github.com/square/picasso – George

関連する問題