Android Java.lang.OutOfMemoryError带有微小位图

Android Java.lang.OutOfMemoryError带有微小位图,java,android,android-bitmap,Java,Android,Android Bitmap,我正在用java代码为活动的按钮创建绘图。它们只包含两种颜色,一种在顶部,另一种在底部,划分点必须根据用户的分数进行调整 我得到java.lang.OutOfMemoryError,即使在将可绘制内容缩小到1×50像素之后,这对于实际位图来说已经足够好了,因为它将被放大以匹配按钮的大小 这是关于内存泄漏的吗?我找到的所有说明都是关于可下载图像的,这些图像可能太大,应用程序无法处理,但我怀疑图像中的50像素是否太多 我的当前代码(在onStart()期间调用createButton 12次): 我

我正在用java代码为活动的按钮创建绘图。它们只包含两种颜色,一种在顶部,另一种在底部,划分点必须根据用户的分数进行调整

我得到java.lang.OutOfMemoryError,即使在将可绘制内容缩小到1×50像素之后,这对于实际位图来说已经足够好了,因为它将被放大以匹配按钮的大小

这是关于内存泄漏的吗?我找到的所有说明都是关于可下载图像的,这些图像可能太大,应用程序无法处理,但我怀疑图像中的50像素是否太多

我的当前代码(在onStart()期间调用createButton 12次):

我已经尝试了
b.recycle()
,将createDrawable方法的return语句替换为

BitmapDrawable bd = new BitmapDrawable(getResources(), b);
b.recycle();
return bd;
但那没用。 还尝试使用实际按钮大小作为位图大小,以防出现缩放错误,但由于在启动时调用了此操作,
button.getWidth()
button.getHeight()
返回零

编辑:

我试过RGB_565,但没用,我以后可能会用alpha值。错误跟踪,如果有帮助:

... E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.myfirm.project, PID: 29992
   java.lang.OutOfMemoryError
   at android.graphics.BitmapFactory.nativeDecodeAsset(Native Method)
   at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:701)
   at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:526)
   at android.graphics.drawable.Drawable.createFromResourceStream(Drawable.java:889)
   at android.content.res.Resources.loadDrawable(Resources.java:3453)
   at android.content.res.Resources.getDrawable(Resources.java:1893)
   at android.support.v4.content.res.ResourcesCompat.getDrawable(ResourcesCompat.java:55)
   at com.apliki.palikat.MenuActivity.createButtons(MenuActivity.java:112)
   at com.apliki.palikat.MenuActivity.onStart(MenuActivity.java:73)
   at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1177)
   at android.app.Activity.performStart(Activity.java:5592)
   at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2414)
   at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2500)
   at android.app.ActivityThread.access$900(ActivityThread.java:171)
   at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1309)
   at android.os.Handler.dispatchMessage(Handler.java:102)
   at android.os.Looper.loop(Looper.java:146)
   at android.app.ActivityThread.main(ActivityThread.java:5679)
   at java.lang.reflect.Method.invokeNative(Native Method)
   at java.lang.reflect.Method.invoke(Method.java:515)
   at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1291)
   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1107)
   at dalvik.system.NativeStart.main(Native Method)
编辑:

好了,现在它莫名其妙地工作了。不知道为什么,在禁用按钮创建后,我对应用程序的其他部分做了很多更改。现在我又试了一次,效果很好。我也试了几次。o、 o
我将在此处更新任何发现。

尝试将Bitmap.Config.ARGB_8888更改为RGB565:

private void createButton(int points, int id, int color1, int color2, int maxPoints){
        findViewById(id).setBackground(createDrawable(color1, color2, points / maxPoints));
}

private Drawable createDrawable(int color1, int color2, float fillRatio){

    int width = 1;
    int height = 50;

    Bitmap b = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);

    Canvas c = new Canvas(b);
    Paint p = new Paint();

    //fill upper part
    p.setColor(color1);
    c.drawRect(0f, height * (1 - fillRatio), width, height, p);

    //fill lower part
    p.setColor(color2);
    c.drawRect(0f, 0f, width, height * (1 - fillRatio), p);

    BitmapDrawable bd = new BitmapDrawable(getResources(), b);
    b.recycle();
    return bd;    
}

正如您在12次调用中所说的那样,您在每次调用中创建一个不同的位图对象和BitmapDrawable对象,假设大小为150kb,则仅位图的内存中会额外增加1800 KB。 尝试重用您的元素(对象、位图和图像),并在Android Studio中检查内存使用情况以减少内存使用

您可以使用请求更大的位图大小,但这在任何预蜂窝设备上都不起作用

请加上
android:largeHeap=“true”
在应用程序标记的清单中。

从哪里获得OOM?它是在位图分配期间可复制的,还是发生在代码的某个独立部分?您是在单独的线程中还是在主线程中执行此操作?请发布实际堆栈跟踪。1*50像素的位图如何占用150KB的内存?位图的内存占用仍然与大小成比例,对吗?我不确定它是否成比例,我认为这取决于你如何做。在Android Studio中分析你的应用程序内存消耗,你会有一个更好的答案。这里有更多关于位图和内存的信息:我会试试,但问题是,我不需要。我正在创建的位图是1*50像素,ARGB_8888表示每个像素的字节数,因此所有12个位图的内容只需要2.4KB的内存,加上一些元数据,应该只有几个字节!
private void createButton(int points, int id, int color1, int color2, int maxPoints){
        findViewById(id).setBackground(createDrawable(color1, color2, points / maxPoints));
}

private Drawable createDrawable(int color1, int color2, float fillRatio){

    int width = 1;
    int height = 50;

    Bitmap b = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);

    Canvas c = new Canvas(b);
    Paint p = new Paint();

    //fill upper part
    p.setColor(color1);
    c.drawRect(0f, height * (1 - fillRatio), width, height, p);

    //fill lower part
    p.setColor(color2);
    c.drawRect(0f, 0f, width, height * (1 - fillRatio), p);

    BitmapDrawable bd = new BitmapDrawable(getResources(), b);
    b.recycle();
    return bd;    
}