简体   繁体   English

背景图像内存泄漏

[英]background image memory leak

I found few topics describing similar problems, but not found a solution for memory leaks being created by pretty simple Android app: 我发现很少有主题描述类似的问题,但找不到非常简单的Android应用程序创建的内存泄漏解决方案:

AndroidManifest.xml : 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 : 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 : 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: 在更改设备的方向(NVIDIA Tegra Note 7)时,logcat注意:

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) 每个周转大约增加了13MB(用于最大版本的图片)

up to my heap max (64MB): 最多达到我的堆最大容量(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.. dpidrawable- [X | M | L]当我从抽拉-陆地[| | M L X]删除ui.png(其被设置为背景)的问题不会保留dpi的文件夹中的res文件夹..所以,如果我背景图片只有一个版本,我可以将设备打开一个星期。

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: //编辑:我设法进行了几次处置,回收,销毁,清空资源或其持有人的尝试,最后一次是基于Aeshang的建议:


=== version 2.0 === === 2.0版 ===

Resources.java : 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 : 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;
}

Use third party libraries to load the drawables 使用第三方库加载可绘制对象

like Picasso or Universal Image Loader PicassoUniversal Image Loader

They will automatically handle large bitmaps 他们将自动处理大位图

And coming to drawables 来到绘画

User 1920X1080 resolution images and put them drawable-xxhdpi folder every thing works fine 用户使用1920X1080分辨率的图像并将其放置在drawable-xxhdpi文件夹中,一切正常

Ok, 好,

this should definitely work. 这绝对应该工作。 Tested in on two other devices, and altrough app is complaining about high memory heap grow. 在另外两个设备上进行了测试,而altrough应用程序则抱怨内存堆增长过快。 It is gc'ing right after. 之后就来了。

My tegra note 7 is THE pain. 我的整体笔记7是痛苦。 I will have to find out the right source of this hell. 我将不得不找出这个地狱的正确来源。

//edit: fine, calling // edit:很好,调用

System.gc();

in onDestroy() of MainActivity 在MainActivity的onDestroy()中

and app lasts forever.. who knows why? 和应用程序永远存在..谁知道为什么?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM