背景图片的内存泄漏 [英] background image memory leak

查看:391
本文介绍了背景图片的内存泄漏的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我发现几个主题描述了类似的问题,但没有发现内存泄漏的解决方案正由pretty简单的Andr​​oid应用程序创建的:

的Andr​​oidManifest.xml

 <?XML版本=1.0编码=UTF-8&GT?;
<清单的xmlns:机器人=htt​​p://schemas.android.com/apk/res/android
          包=cz.reloecc.testBackground
          安卓版code =1
          机器人:=的versionName1.0>
    <采用-SDK安卓的minSdkVersion =10/>
    <应用机器人:标签=@字符串/ APP_NAME
              机器人:图标=@绘制/ ic_launcher>
        <活动机器人:名字=TestBackgroundActivity
                  机器人:主题=@安卓风格/ Theme.Black.NoTitleBar.Fullscreen
                  机器人:标签=@字符串/ APP_NAME>
            &所述;意图滤光器>
                <作用机器人:名字=android.intent.action.MAIN/>
                <类机器人:名字=android.intent.category.LAUNCHER/>
            &所述; /意图滤光器>
        < /活性GT;
    < /用途>
< /清单>

结果
的main.xml

 <?XML版本=1.0编码=UTF-8&GT?;
< LinearLayout中的xmlns:机器人=htt​​p://schemas.android.com/apk/res/android
          机器人:方向=垂直
          机器人:layout_width =FILL_PARENT
          机器人:layout_height =FILL_PARENT
          机器人:背景=@绘制/ UI>
< / LinearLayout中>

结果
TestBackgroundActivity.java

 公共类TestBackgroundActivity延伸活动{
    @覆盖
    公共无效的onCreate(捆绑savedInstanceState){
        super.onCreate(savedInstanceState);
        的setContentView(R.layout.main);
    }
}

结果
虽然改变了我的设备的方位(的NVIDIA Tegra注7)logcat的是指出:

  cz.reloecc.testBackground I / dalvikvm堆:堆成长(frag的情况下),以35.625MB为12904976个字节分配

,大约有13MB除了每个周转(图像的最大版本)

到我的最大堆(64MB):

  cz.reloecc.testBackground E / dalvikvm堆:出于对12904976字节分配内存。
cz.reloecc.testBackground I / dalvikvm:在android.graphics.BitmapFactory.nativeDe $ C $检测板(本机方法)
..
cz.reloecc.testBackground I / dalvikvm:在cz.reloecc.testBackground.TestBackgroundActivity.onCreate(TestBackgroundActivity.java:13)

结果
但是!
问题的坚持,当我从绘制,陆地删除ui.pn​​g(被设置为背景)[X | M | L] DPI drawable- [X | M | L] DPI 在res文件夹文件夹..
所以,如果我有背景图像只有一个版本,我可以把设备漫长的一周。

这是我的问题:如何处理可绘制的多个版本(设置为背景),以避免内存泄漏。

结果
//编辑:我管理的处置,回收,销毁,归零资源或其持有人试了几次,最后一个是基于Aeshang的建议:

结果
===的 2.0 的===

Resources.java

 公共类资源{    公共资源(上下文的背景下){
        this.context =背景;
    }    公众可绘制的getImage(INT ID){
        如果(images.indexOfKey(ID)小于0){
            可绘制可绘制= context.getResources()getDrawable(ID)。
            images.put(ID,绘制);
        }        返回images.get(ID);
    }    公共无效disposeImages(){
        INT关键;        的for(int i = 0; I< images.size();我++){
            键= images.keyAt(I)
            可绘制可绘制= images.get(键);            如果(绘制的instanceof BitmapDrawable){
                如果(绘制的instanceof BitmapDrawable){
                    Log.i(TestBackgroundActivity.LOG_TAG,回收形象+键);
                    ((BitmapDrawable)抽拉).getBitmap()再循环();
                }
            }
        }
    }    公共无效disposeAll(){
        disposeImages();
        images.clear();
    }    私人SparseArray<&可绘制GT;照片=新SparseArray<&可绘制GT;();
    私人上下文的背景下;
}

结果
TestBackgroundActivity.java

 公共类TestBackgroundActivity延伸活动{    公共静态字符串LOG_TAG =[TestBG];    @覆盖
    公共无效的onCreate(捆绑savedInstanceState){
        super.onCreate(savedInstanceState);
        的setContentView(R.layout.main);        资源=新资源(getApplicationContext());
        的LinearLayout mainLayout =(的LinearLayout)findViewById(R.id.mainLayout);
        mainLayout.setBackgroundDrawable(resources.getImage(R.drawable.ui));
    }    @覆盖
    保护无效的onDestroy(){
        resources.disposeAll();        super.onDestroy();
    }    私人资源的资源;
}


解决方案

好吧,

这绝对应该工作。经测试,在其他两个设备,并altrough应用抱怨高内存堆增长。它之后gc'ing。

我的Tegra注7是痛苦。我将不得不找出这个地狱的权利来源。

//编辑:
细,要求

 的System.gc();

在MainActivity中的onDestroy()

和应用是永恒的..谁知道这是为什么?

I found few topics describing similar problems, but not found a solution for memory leaks being created by pretty simple Android app:

AndroidManifest.xml:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
          package="cz.reloecc.testBackground"
          android:versionCode="1"
          android:versionName="1.0">
    <uses-sdk android:minSdkVersion="10"/>
    <application android:label="@string/app_name"
              android:icon="@drawable/ic_launcher">
        <activity android:name="TestBackgroundActivity"
                  android:theme="@android:style/Theme.Black.NoTitleBar.Fullscreen"
                  android:label="@string/app_name">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>
                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>
    </application>
</manifest>


main.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
          android:orientation="vertical"
          android:layout_width="fill_parent"
          android:layout_height="fill_parent"
          android:background="@drawable/ui">
</LinearLayout>


TestBackgroundActivity.java:

public class TestBackgroundActivity extends Activity {
    @Override
    public void onCreate(Bundle savedInstanceState){
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
    }
}


While changing an orientation of my device (nvidia Tegra Note 7) logcat is noting:

cz.reloecc.testBackground I/dalvikvm-heap﹕ Grow heap (frag case) to 35.625MB for 12904976-byte allocation

with roughly 13MB addition on every turnaround (for biggest version of image)

up to my heap max (64MB):

cz.reloecc.testBackground E/dalvikvm-heap﹕ Out of memory on a 12904976-byte allocation.
cz.reloecc.testBackground I/dalvikvm﹕ at android.graphics.BitmapFactory.nativeDecodeAsset(Native Method)
..
cz.reloecc.testBackground I/dalvikvm﹕ at cz.reloecc.testBackground.TestBackgroundActivity.onCreate(TestBackgroundActivity.java:13)


BUT! problem does not persist when I delete ui.png (which is set as background) from drawable-land-[x|m|l]dpi OR drawable-[x|m|l]dpi folder in res folder.. so if I have only one version of background image, I can turn device for a long week..

And here is my question: How to handle multiple versions of drawables (set as background) to avoid memory leaks?


//EDIT: I managed few tries of disposing, recycling, destroying, nulling resources or their holders, the last one is based on Aeshang's suggestion:


=== version 2.0 ===

Resources.java:

public class Resources {

    public Resources(Context context){
        this.context = context;
    }

    public Drawable getImage(int id){
        if(images.indexOfKey(id) < 0){
            Drawable drawable = context.getResources().getDrawable(id);
            images.put(id, drawable);
        }

        return images.get(id);
    }

    public void disposeImages(){
        int key;

        for(int i = 0; i < images.size(); i++) {
            key = images.keyAt(i);
            Drawable drawable = images.get(key);

            if(drawable instanceof BitmapDrawable){
                if(drawable instanceof BitmapDrawable){
                    Log.i(TestBackgroundActivity.LOG_TAG, "Recycling image " + key);
                    ((BitmapDrawable)drawable).getBitmap().recycle();
                }
            }
        }
    }

    public void disposeAll(){
        disposeImages();
        images.clear();
    }

    private SparseArray<Drawable> images = new SparseArray<Drawable>();
    private Context context;
}


TestBackgroundActivity.java:

public class TestBackgroundActivity extends Activity {

    public static String LOG_TAG = "[TestBG]";

    @Override
    public void onCreate(Bundle savedInstanceState){
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        resources = new Resources(getApplicationContext());
        LinearLayout mainLayout = (LinearLayout)findViewById(R.id.mainLayout);
        mainLayout.setBackgroundDrawable(resources.getImage(R.drawable.ui));
    }

    @Override
    protected void onDestroy(){
        resources.disposeAll();

        super.onDestroy();
    }

    private Resources resources;
}

解决方案

Ok,

this should definitely work. Tested in on two other devices, and altrough app is complaining about high memory heap grow. It is gc'ing right after.

My tegra note 7 is THE pain. I will have to find out the right source of this hell.

//edit: fine, calling

System.gc();

in onDestroy() of MainActivity

and app lasts forever.. who knows why?

这篇关于背景图片的内存泄漏的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆