Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/jenkins/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android 画布:尝试使用回收的位图错误_Android_Android Layout_Bitmap_Android Asynctask - Fatal编程技术网

Android 画布:尝试使用回收的位图错误

Android 画布:尝试使用回收的位图错误,android,android-layout,bitmap,android-asynctask,Android,Android Layout,Bitmap,Android Asynctask,我是一个相当新的程序员,所以任何建议都将不胜感激。我有一个类,它在每次调用时都在循环中运行AsyncTask。异步任务如下所示: public class LoadImageTask extends AsyncTask<Void, Void, Void> { Context c; ViewHolder vh; public Bitmap bm; ViewGroup container; LinearLayout layout; pu

我是一个相当新的程序员,所以任何建议都将不胜感激。我有一个类,它在每次调用时都在循环中运行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();
        }

    }
}
公共类LoadImageTask扩展了AsyncTask{
上下文c;
视窗座;
公共位图bm;
视图组容器;
线性布局;
公共LoadImageTask(上下文c、视图持有者vh、视图组容器、,
线性布局(linlay){
这个。vh=vh;
这个.c=c;
this.container=容器;
this.layout=linlay;
}
受保护的Void doInBackground(Void…参数){
工具=新工具();
this.bm=tools.getAlbumart(this.c,vh.albumID);
返回null;
}
受保护的void onPostExecute(void参数){
vh.iv.setImageBitmap(this.bm);
this.layout.addView(this.container);
如果(bm!=null){
bm.recycle();
}
}
}
ViewHolder vh-包含两个文本视图和一个图像视图的类

视图组容器-用于为我所做的xml设计充气的容器(带有两个文本视图和一个图像视图)

LinearLayout linlay-我正在向其中添加容器的滚动视图布局(根据我希望在该视图中显示的元素数量进行扩展)


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

此时,您正在回收位图,然后再将其渲染到UI上,因为
setImageBitmap(bm)
将只准备ImageView以渲染提供的位图。渲染将安排在UI下一次失效时进行

bm.recycle()
在位图渲染之前被调用,因此应用程序在尝试绘制位图时将崩溃

在UI中使用位图时,不能循环使用位图,位图必须保存在内存中。在大多数情况下,Android可以很好地处理回收,但是如果你需要自己回收,你需要确保以后不要使用位图实例(在这种情况下,位图实例将在稍后渲染)

  • 如果位图使用太多内存,您应该尝试缩小它!(例如:256x256的Albumart是不错的选择)

  • 如果您在Android 3.0及以上版本上运行应用程序,则无需调用recycle(),因为GC将完美地处理它

  • 见pär Nils Amsen的回答


  • 所以,我的应用程序所做的就是创建一堆歌曲对象(这些对象是预先初始化的)。然后,它根据歌曲的给定特征为每首歌曲设置文本视图和图像视图。对于我正在处理的每首歌曲,我都会运行AsyncTask,因此我最终会拥有大量位图(与图像数量相同的歌曲),因此我需要一种方法在它们被绘制后进行回收,否则会占用太多内存。我有错误的方法吗?不一定,这是一个优化的问题。对于200x200px的相册艺术,对于一部较新的手机来说,内存中一次大约有8张相册,因此您有足够的RAM,可以在大多数设备上加载略多于设备屏幕像素的内容。我的建议是使用RecyclerView并延迟加载图像,因为它们将显示在屏幕上,还要确保您使用的是适当缩放的图像(不是800x800,而只需要50x50)。为了帮助实现这一切,请使用惰性加载图像,这是一个很好的图像加载库,它尊重RAM的使用。太棒了!我肯定会利用延迟加载和RecycleView。谢谢你的提示!你真的救了我的命!哦,哇!创建另一个缩放位图并循环使用原始位图修复了该问题!缩小尺寸确实有帮助,谢谢!