java - Android - 使用位图的 AsyncTask - OutOfMemoryError

标签 java android multithreading android-asynctask

<分区>

Possible Duplicate:
OutOfMemory Exception when handling images

我在 AsyncTask 中创建了一个位图,它是这样的:

private WeakReference<Bitmap> myBitmap;
private WeakReference<Bitmap> endResultBitmap;
private ImageView imv;

...

private class SendBitmap extends AsyncTask<Integer, Void, Bitmap> {

public SendBitmap(Bitmap bitmap) {
    myBitmap = new WeakReference<Bitmap>(bitmap);
}

@Override
protected Bitmap doInBackground(Integer... params) {
  Bitmap bm = null;
  bm = getBitmapFromNet(params[0]);

  return bm;
}

然后我想创建接收到的位图会出现两次的位图(一个接一个)

protected void onPostExecute(Bitmap result) {
  endResultBitmap = new WeakReference<Bitmap>(Bitmap.createBitmap(result.getWidth() * 2, result.getHeight(), result.getConf()));

  Canvas canvas = new Canvas(endResultBitmap.get());
  canvas.drawBitmap(result, 0, 0, null);
  canvas.drawBitmap(result, result.getWidth(), 0, null);

  imv.setImageBitmap(endResultBitmap);
}

然后我有我的 onCancelled() 方法:

@Override
protected void onCancelled(Bitmap result) {
  if(endResultBitmap!=null) {
    endResultBitmap.recycle();
    endResultBitmap = null;
  }
}

问题是,如果我多次执行此 AsyncTask,堆就会疯狂增长。 我在按下按钮时执行 AsyncTask,但起初我这样做:

public void onClicked(View v) {

  if(asyncTaskInstance != null) 
    asyncTaskInstance.cancel();

  asynctaskInstance.execute(2);
}

但是,堆再次疯狂增长,在某个时候它会因 OutOfMemoryError 而崩溃。

有什么想法吗?我的任务设计有问题吗?

最佳答案

Android 对应用程序有一些内存限制(如果我没记错的话是 16 MB),而且该图像在未压缩格式下太大了。 this question 中有一些有趣的讨论.

要解决它,afaik只有两种方法:
1. 缩小图片占用内存
2. 使用 NDK 在 native 代码中加载图像。

致 1.:我不知道你到底想做什么,也不知道这是否真的是一个可行的选择。如果是,您可能需要从网上下载图像文件并使用 BitmapFactory 类打开它。有一些静态函数接受 BitmapFactory.Options。目的。使用此 Options 对象中的 inSampleSize 在加载时将图像大小减小特定因子(顺便说一下,inSampleSize 应该是 2 的幂)。

To 2.: 我上面提到的内存限制不适用于 native 代码。因此,您可能能够以 native 方式加载图像并显示。我对此没有任何经验,我只知道这是可能的,但谷歌搜索应该会找到一些结果。

关于java - Android - 使用位图的 AsyncTask - OutOfMemoryError,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6982532/

相关文章:

java - 如何处理包含空文件名文件的 zip 文件

java - Windows 和 Linux 之间的 ActionListener 差异

java - 在 Libgdx 中创建另一个纹理时,我应该调用 dispose() 纹理吗?

android - Apache 2.4.6 - 发送 GZIP 内容有时会导致 "read more bytes of request body than expected"

c# - 如何创建跨进程工作的类级互斥量

Java GC 线程瓶颈在实践中?

java - 在 Java 8 中实现 Monad

android - 为什么由于注释而无法在 onCreate() 中添加方法?

php - 在 yii2 中创建扩展线程的自定义类

java - 在数组的每一列中查找最小值和最大值