平时用到的优化,也许有遗漏,但是尽量列出来以防生疏,大概都是别重复创建对象,注意对象的回收是影响性能,对象泄漏啊什么的,线程安全的java 类,还需要注意代码可读性,可读性才提供给他人修改你的代码可能。推荐实时监测工具Leaks、如果对局部重复检查,还需要结合开发工具自带的内存泄漏检查
1、Bitmap使用时候,不要马上收回了,因为对象引用还存在,而且界面还未注销,还重复使用的,但忘记在哪个版本后就无需这样做了
2、Bitmap 对象清空时候,最好先调用recycle(),虽然做内存泄漏检测时候,发现对象已经不存在,但是recycle进行C层面回收,在哪个版本开始就不需要手动注销了。
3、Handler 使用,有避免内存泄漏情况,因为它是队列形式,而持有当前Activity对象,网上有资料,例子用法
public Handler handler = new MyHandler(this);
static class MyHandler extends Handler {
final WeakReference<BaseActivity> mActivityReference;
MyHandler(BaseActivity activity) {
mActivityReference = new WeakReference<BaseActivity>(activity);
}
@Override
public void handleMessage(Message msg) {
final BaseActivity activity = mActivityReference.get();
if (activity != null || !activity.isdestroy) {
activity.handleMessage(msg);
}
}
}
4、Handler 也要回收
@Override
protected void onDestroy() {
super.onDestroy();
handler.removeCallbacksAndMessages(null);
handler = null;
}
5、别把当前的Context 传到初始化单例中去,因为单例对象周期和你的Context周期不一样,这样就容易导致泄漏,Context可以使用getApplicationContext()
public class AppManager {
private static AppManager instance;
private Context context;
private AppManager(Context context) {
this.context = context;//getApplicationContext()更好
}
public static AppManager getInstance(Context context) {
if (instance == null) {
instance = new AppManager(context);
}
return instance;
}
}
6、匿名内部类的使用,特别是周期比较长的,如线程方面的
Runnable runnable = new Runnable() {
@Override
public void run() {
//这样的匿名内部类会有引用到当前Activity,存在泄漏风险
}
};
可以这样试试
Runnable runnable = new TestRunnable();
static class TestRunnable implements Runnable {
@Override
public void run() {
}
}
7、做了某些监听,如果是add类型的,建议用完都remove掉
getWindow().getDecorView().post(new Runnable() {
@Override
public void run() {
handler.post(new Runnable() {
@Override
public void run() {
Message msg = handler.obtainMessage(0);
msg.obj = "333";
handler.sendMessage(msg);
}
});
getWindow().getDecorView().removeCallbacks(this);
}
});
8、一些View,建议别用static ,这样全局以后,Context就无法回收
private static final class ViewHolder {
private static ImageView mPhotoView;
private static TextView mCounter;
}
9.SharedPreference 不能滥用
- 解析sp的时候会产生大量的临时对象,导致频繁GC,引起界面卡顿。
- 这些key和value会永远存在于内存之中,占用大量内存。
-
下面是默认的sp实现SharedPreferenceImpl这个类的getString函数:
public String getString(String key, @Nullable String defValue) { synchronized (this) { awaitLoadedLocked(); String v = (String)mMap.get(key); return v != null ? v : defValue; } }
继续看看这个awaitLoadedLocked:
private void awaitLoadedLocked() { while (!mLoaded) { try { wait(); } catch (InterruptedException unused) { } } }
一把锁就是挂在那里!!这意味着,如果你直接调用getString,主线程会等待加载sp的那么线程加载完毕!这不就把主线程卡住了么?