相同的 Controller 类型控件,红框中在 Android Profiler 显示大内存,且发现对象不断创建没释放
下图标准了2个方法,哪个习惯用哪个
主要通过使用dump查看各个代码类的堆栈信息,查找大内存的类对象。
从内存泄露现象发现,对象没有被回收
查看问题代码
package com.lava.powersave.fuelguage;
import android.content.Context;
import android.database.ContentObserver;
import android.os.Handler;
import android.os.Message;
import android.provider.Settings;
import android.support.v14.preference.SwitchPreference;
import android.support.v7.preference.PreferenceScreen;
import android.support.v7.preference.Preference;
import android.support.v7.preference.Preference.OnPreferenceClickListener;
import android.util.Log;
import com.android.settingslib.core.AbstractPreferenceController;
import com.android.settingslib.core.lifecycle.events.OnDestroy;
import com.lava.powersave.LavaPowerSaveConstant;
import com.lava.powersave.LavaPowerSaveUtil;
public class LavaPowerSavePreferenceController extends AbstractPreferenceController implements OnPreferenceClickListener, OnDestroy {
private static final String TAG = LavaPowerSavePreferenceController.class.getSimpleName();
private static final String KEY_LAVA_POWER_SAVE = "key_lava_power_save";
private static final int MSG_UPDATE_SWITCH = 0;
private static final long WAIT_FOR_SWITCH_ANIM = 500;
private static final int MSG_UPDATE_CLICKABLE = 1;
private static final long WAIT_FOR_CLICKABLE = 3000;
private Context mContext;
private SwitchPreference mBatterySaverPref;
public LavaPowerSavePreferenceController(Context context) {
super(context);
this.mContext = context;
mContext.getContentResolver().registerContentObserver(Settings.System.getUriFor(LavaPowerSaveConstant.KEY_POWER_SAVE_MODE), false, mPowerSaveObserver);
}
@Override
public void onDestroy() {
mContext.getContentResolver().unregisterContentObserver(mPowerSaveObserver);
}
private final Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_UPDATE_SWITCH:
mBatterySaverPref.setChecked(LavaPowerSaveUtil.isLavaPowerSaveMode(mContext));
break;
case MSG_UPDATE_CLICKABLE:
mBatterySaverPref.setEnabled(true);
break;
}
}
};
@Override
public boolean isAvailable() {
return LavaPowerSaveConstant.LAVA_POWER_SAVE ? true : false;
}
@Override
public String getPreferenceKey() {
return KEY_LAVA_POWER_SAVE;
}
@Override
public void displayPreference(PreferenceScreen screen) {
super.displayPreference(screen);
mBatterySaverPref = (SwitchPreference) screen.findPreference(KEY_LAVA_POWER_SAVE);
mBatterySaverPref.setOnPreferenceClickListener(this);
}
@Override
public void updateState(Preference preference) {
mHandler.sendEmptyMessage(MSG_UPDATE_SWITCH);
}
@Override
public boolean onPreferenceClick(Preference preference) {
mBatterySaverPref.setEnabled(false);
mHandler.sendEmptyMessageDelayed(MSG_UPDATE_CLICKABLE, WAIT_FOR_CLICKABLE);
LavaPowerSaveUtil.startLavaPowerSaveMode(mContext, mBatterySaverPref.isChecked());
mHandler.sendEmptyMessageDelayed(MSG_UPDATE_SWITCH, WAIT_FOR_SWITCH_ANIM);
return true;
}
private ContentObserver mPowerSaveObserver = new ContentObserver(new Handler()) {
public void onChange(boolean selfChange) {
mHandler.sendEmptyMessage(MSG_UPDATE_SWITCH);
}
};
}
发现上述Handle的使用存在问题,注释掉Handle的方法,调用发现内存泄露问题消失
具体如下,本文主要介绍Android Profiler分析实例工具使用
优化了Handle的回收,防止内存泄露
package com.lava.powersave.fuelguage;
import android.content.Context;
import android.database.ContentObserver;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.provider.Settings;
import android.support.v14.preference.SwitchPreference;
import android.support.v7.preference.PreferenceScreen;
import android.support.v7.preference.Preference;
import android.support.v7.preference.Preference.OnPreferenceClickListener;
import android.util.Log;
import com.android.settingslib.core.AbstractPreferenceController;
import com.android.settingslib.core.lifecycle.events.OnDestroy;
import com.lava.powersave.LavaPowerSaveConstant;
import com.lava.powersave.LavaPowerSaveUtil;
public class LavaPowerSavePreferenceController extends AbstractPreferenceController implements OnPreferenceClickListener, OnDestroy {
private static final String TAG = LavaPowerSavePreferenceController.class.getSimpleName();
private static final String KEY_LAVA_POWER_SAVE = "key_lava_power_save";
private static final int MSG_UPDATE_SWITCH = 0;
private static final long WAIT_FOR_SWITCH_ANIM = 500;
private static final int MSG_UPDATE_CLICKABLE = 1;
private static final long WAIT_FOR_CLICKABLE = 3000;
private Context mContext;
private final H mHandler = new H();
private SwitchPreference mBatterySaverPref;
public LavaPowerSavePreferenceController(Context context) {
super(context);
this.mContext = context;
mContext.getContentResolver().registerContentObserver(Settings.System.getUriFor(LavaPowerSaveConstant.KEY_POWER_SAVE_MODE), false, mPowerSaveObserver);
}
@Override
public void onDestroy() {
mContext.getContentResolver().unregisterContentObserver(mPowerSaveObserver);
}
private final class H extends Handler {
private H() {
super(Looper.getMainLooper());
}
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_UPDATE_SWITCH:
mBatterySaverPref.setChecked(LavaPowerSaveUtil.isLavaPowerSaveMode(mContext));
break;
case MSG_UPDATE_CLICKABLE:
mBatterySaverPref.setEnabled(true);
break;
}
}
}
@Override
public boolean isAvailable() {
return LavaPowerSaveConstant.LAVA_POWER_SAVE ? true : false;
}
@Override
public String getPreferenceKey() {
return KEY_LAVA_POWER_SAVE;
}
@Override
public void displayPreference(PreferenceScreen screen) {
super.displayPreference(screen);
mBatterySaverPref = (SwitchPreference) screen.findPreference(KEY_LAVA_POWER_SAVE);
mBatterySaverPref.setOnPreferenceClickListener(this);
}
@Override
public void updateState(Preference preference) {
mHandler.sendEmptyMessage(MSG_UPDATE_SWITCH);
}
@Override
public boolean onPreferenceClick(Preference preference) {
mBatterySaverPref.setEnabled(false);
mHandler.sendEmptyMessageDelayed(MSG_UPDATE_CLICKABLE, WAIT_FOR_CLICKABLE);
LavaPowerSaveUtil.startLavaPowerSaveMode(mContext, mBatterySaverPref.isChecked());
mHandler.sendEmptyMessageDelayed(MSG_UPDATE_SWITCH, WAIT_FOR_SWITCH_ANIM);
return true;
}
private ContentObserver mPowerSaveObserver = new ContentObserver(new Handler()) {
public void onChange(boolean selfChange) {
mHandler.sendEmptyMessage(MSG_UPDATE_SWITCH);
}
};
}
重新dump后结果