Android - AsyncTask 使用位图 - OutOfMemoryError

发布于 2024-11-28 14:12:31 字数 1692 浏览 0 评论 0原文

可能的重复:
处理图像时出现 OutOfMemory 异常

我在 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 崩溃。

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

Possible Duplicate:
OutOfMemory Exception when handling images

I have a Bitmap creation within a AsyncTask, which goes like this:

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;
}

And then I want to create Bitmap on which the received Bitmap would appear twice (one next to another)

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);
}

then I have my onCancelled() method:

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

The thing is that if I execute this AsyncTask couple of times, the heap grows as mad.
I execute the AsyncTask when a button is pressed, but at first I do:

public void onClicked(View v) {

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

  asynctaskInstance.execute(2);
}

But again, the Heap grows as mad and at some point it will crash with OutOfMemoryError.

Any idea? Do I have something wrong in my Design of the task?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

So要识趣 2024-12-05 14:12:31

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

要解决这个问题,据我所知只有两种方法:
1.减小图片大小以减少内存消耗
2. 使用 NDK 以本机代码加载图像。

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

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

Android has some memory limits for apps (16 MB if i remember correctly), and that image is too big in an uncompressed format. Theres some interesting discussion in this question.

To solve it, there are afaik only two ways:
1. Reduce the size of the image to consume less memory
2. Load the image in native code using the NDK.

To 1.: I don't know what exactly you are trying to do and can't tell if thats really a viable option. If it is, you may want download the image file from the net and open it with the BitmapFactory class. There are some static functions that take an BitmapFactory.Options object. Use inSampleSize from this Options object to reduce the image size by a certain factor at loading time (inSampleSize should be a power of two by the way).

To 2.: The memory limits that I mentioned above don't apply to native code. So you may be able to load the image and display in a native way. I don't have any experience with that, I just know that it's possible, but googling around should turn up a few results.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文