【问题标题】:Canvas: Trying to use a recycled bitmap error画布:尝试使用回收的位图错误
【发布时间】:2017-10-01 01:18:52
【问题描述】:

我是一个相当新的程序员,所以任何建议都将不胜感激。我有一个类,每次调用它时都会在循环中运行 AsyncTask。 AsyncTask 看起来像这样:

public class LoadImageTask extends AsyncTask<Void, Void, Void> {

    Context c;
    ViewHolder vh;
    public Bitmap bm;
    ViewGroup container;
    LinearLayout layout;

    public LoadImageTask(Context c, ViewHolder vh, ViewGroup container, 
    LinearLayout linlay) {

        this.vh = vh;
        this.c = c;
        this.container = container;
        this.layout = linlay;
    }

    protected Void doInBackground(Void... params) {
        Tools tools = new Tools();
        this.bm = tools.getAlbumart(this.c, vh.albumID);
        return null;
    }

    protected void onPostExecute(Void param) {
        vh.iv.setImageBitmap(this.bm);
        this.layout.addView(this.container);
        if (bm!=null) {
            bm.recycle();
        }

    }
}

ViewHolder vh - 包含 2 个文本视图和一个 Imageview 的类

ViewGroup 容器 - 用于扩充我所做的 xml 设计的容器(带有 2 个文本视图和一个 ImageView)

LinearLayout linlay - 我将容器添加到的滚动视图布局(根据我在该视图中想要的元素数量来扩展它)

我创建的位图使用了太多内存,所以我想回收它们,但是每次我在将容器添加到布局后尝试回收它们时,它都会说我正在尝试使用回收的位图(当我在将容器添加到屏幕后清楚地调用回收时)......我在这一点上被难住了。任何帮助都会很好。

【问题讨论】:

    标签: android android-layout bitmap android-asynctask


    【解决方案1】:

    目前,您在将位图渲染到 UI 之前对其进行回收,因为setImageBitmap(bm) 只会准备 ImageView 以渲染提供的位图。渲染将安排在 UI 下一次失效时进行。

    bm.recycle() 在 Bitmap 被渲染之前被调用,所以应用在尝试绘制 Bitmap 时会崩溃。

    在 UI 中使用 Bitmap 时不能回收它,Bitmap 必须保存在内存中。在大多数情况下,Android 可以很好地处理回收,但如果您需要自己回收,则需要确保之后不使用 Bitmap 实例(在这种情况下,稍后将呈现 Bitmap 实例)。

    【讨论】:

    • 所以,我的应用正在做的是创建一堆 Song 对象(预先初始化)。然后对于每首歌曲,它会根据歌曲的给定特征设置 textviews 和 imageviews。对于我正在处理的每首歌曲,我都会运行 AsyncTask,因此我最终会拥有大量位图(相同数量的带有图像的歌曲),因此我需要一种在绘制后回收它们的方法,否则会占用太多内存用过的。我有错误的方法吗?
    • 不一定,是优化问题。在大多数设备上,您有足够的 RAM 来加载比设备屏幕上的像素多一点的内容,对于 200x200 像素的专辑封面,对于较新的手机来说,内存中一次大约有 8 个专辑。我的建议是使用 RecyclerView 并延迟加载要在屏幕上显示的图像,还要确保您使用的是适当缩放的图像(不是 800x800,而只需要 50x50)。为了帮助解决所有这些问题,请使用 square.github.io/picasso 懒惰地加载图像,这是一个很棒的图像加载库,可以使用 RAM。
    • 太棒了!我肯定会使用延迟加载和 RecycleView。非常感谢您的提示!
    • 你真的救了我的命!
    【解决方案2】:
    1. 如果位图使用太多内存,您应该尝试缩小它! (例如:256x256 的相册是不错的选择)

    2. 如果您在 Android 3.0 及更高版本上运行应用,则无需调用 recycle(),因为 GC 会完美处理。

    3. 参见 Pär Nils Amsen 的回答。

    【讨论】:

    • 哇哦!创建另一个缩放位图并回收原始位图解决了问题!缩小它确实有帮助,谢谢!
    猜你喜欢
    • 2015-09-21
    • 2013-07-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-03
    • 2011-12-20
    • 2015-12-04
    相关资源
    最近更新 更多