我正在处理的应用是泄漏内存。据我所知,我正在做一切建议: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>
答案 0 :(得分:1)
jbww,
我在一些活动中注意到了类似的行为,所以我添加了
android:configChanges="keyboardHidden|orientation"
到Activity
中的AndroidManifest.xml
,然后重写onConfigurationChanged()
重新加载必要的信息。
每次旋转设备时,我都不会注意到堆的增长。
我希望这也适合你。