内存泄漏非常简单的应用程序

时间:2011-03-18 19:08:01

标签: android memory-leaks

我正在处理的应用是泄漏内存。据我所知,我正在做一切建议:http://developer.android.com/resources/articles/avoiding-memory-leaks.html

我已将我的应用程序切换为一个非常简单的应用程序,除了设置背景图像之外什么都不做。每次我进行屏幕方向更改时,应用程序都会泄漏30k-50k的内存。

所以我怀疑以下情况:

的setContentView() 和 findViewById()

我是否需要在与这些调用相关的onDestroy()中执行某些操作,以将它们与Activity分离?

我也有几个问题。在onDestroy()中,我调用setBackgroundResource(0)。我相信如果我不这样做,背景位图的Drawable将保持对视图的回调,这将导致整个上下文的泄漏。这是真的?将此调用添加到onDestroy()当然似乎对泄漏的大小产生了很大的影响。在视图构造函数中,我尝试通过使用Application上下文进行super()调用来删除对活动的一些引用,而不是活动上下文。这实际上是提供这种好处还是重要的?这样做有副作用,我应该注意吗?

代码和XML如下:此时我真的不明白为什么它应该泄漏内存。任何启蒙都会受到高度赞赏。

MemLeak.java

package randombrand.MemLeak;

import randombrand.MemLeak.R;
import randombrand.MemLeak.MLView;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;

public class MemLeak extends Activity {

    private MLView mmlView;
    private static final String strmlBundle = "Mem Leak";

    @Override
    public void onCreate(Bundle icicle) {
        super.onCreate(icicle);
        setContentView(R.layout.memleak_layout);
        mmlView = (MLView) findViewById(R.id.viewMemLeak);
        try {
            mmlView.Init(this);
            SetBackgroundBitmap();
        } catch (Exception ex) {
            Log.e(strmlBundle, "Failed to launch Mem Leak." + ex);
            this.finish();
        }
        if (icicle == null) {
            mmlView.SetActive(true);
        } else {
            Bundle bundle = icicle.getBundle(strmlBundle);
            if (bundle != null) {
                mmlView.SetActive(true);
                mmlView.invalidate();
            } else {
                mmlView.SetActive(false);
            }
        }
    }

    @Override
    protected void onPause() {
        super.onPause();
        mmlView.SetActive(false);
    }

    @Override
    protected void onResume() {
        super.onResume();
        mmlView.SetActive(true);
    }

    private void SetBackgroundBitmap() {
        mmlView.setBackgroundResource(R.drawable.dark_background);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        mmlView.setBackgroundResource(0);
    }
}

MLView.java

package randombrand.MemLeak;

import android.content.Context;
import android.graphics.Canvas;
import android.os.Handler;
import android.os.Message;
import android.util.AttributeSet;
import android.view.View;

public class MLView extends View {

    private static final long ltFpDrawDelay = 66;
    Context mContextApp;
    // true when we are not sleeping in the background
    private boolean mfActive = false;

    public MLView(Context context, AttributeSet aSet) {
        super(context.getApplicationContext(), aSet);
    }

    public MLView(Context context, AttributeSet aSet, int nStyle) {
        super(context.getApplicationContext(), aSet, nStyle);
    }

    public void Init(MemLeak mLeak) {
        mContextApp = mLeak.getApplicationContext();
        SetActive(true);
    }

    public void Update() {
        mRedrawHandler.sleep(ltFpDrawDelay);
    }

    public void SetActive(boolean fActive) {
        mfActive = fActive;
        if (fActive) Update();
    }

    @Override
    public void onDraw(Canvas canvas) {
        super.onDraw(canvas);
    }

    private RedrawHandler mRedrawHandler = new RedrawHandler();

    class RedrawHandler extends Handler {

        @Override
        public void handleMessage(Message msg) {
            MLView.this.Update();
            MLView.this.invalidate();
        }

        public void sleep(long ltMillis) {
            this.removeMessages(0);
            sendMessageDelayed(obtainMessage(0), ltMillis);
        }
    }
}

memleak_layout.java

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">

    <randombrand.MemLeak.MLView
        android:id="@+id/viewMemLeak"
        android:layout_width="fill_parent" 
        android:layout_height="fill_parent" />

</FrameLayout>    

的AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="randombrand.MemLeak"
      android:versionCode="1"
      android:versionName="1.0">
    <uses-sdk android:minSdkVersion="5" />

    <application android:icon="@drawable/icon" android:label="@string/app_name"
             android:debuggable="true">
        <activity android:name="MemLeak"
                 android:launchMode="singleInstance"
                 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>

1 个答案:

答案 0 :(得分:1)

jbww,

我在一些活动中注意到了类似的行为,所以我添加了

android:configChanges="keyboardHidden|orientation"

Activity中的AndroidManifest.xml,然后重写onConfigurationChanged()重新加载必要的信息。

每次旋转设备时,我都不会注意到堆的增长。

我希望这也适合你。