内存泄漏及解决方案

时间:2020-11-27 20:56:03

1,内存泄漏:

一般内存泄漏(traditional memory leak)的原因是:当该对象的所有引用都已经释放了,对象仍未被释放。(译者注:Cursor忘记关闭等)
逻辑内存泄漏(logical memory leak)的原因是:当应用不再需要这个对象,当仍未释放该对象的所有引用。

2,产生内存泄漏原因

(1)将Activity或View等对象定义成静态变量,如果这个静态变量在Activity生命周期结束后没有清空,就导致内存泄漏。因为static变量是贯穿这个应用的生命周期的,所以被泄漏的Activity就会一直存在于应用的进程中,不会被垃圾回收器回收。

public class LeakActivity extends AppCompatActivity {

private static Context sContext;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_leak);
sContext = this;
}
}

(2)非静态匿名内部类或非静态内部类,内部类的优势之一就是可以访问外部类,不幸的是,导致内存泄漏的原因,就是内部类持有外部类实例的强引用。

最常见的就是Handler的写法:

private Handler mHandler = new Handler() {

@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
}
};

(3)context 引用不正确

第三方SDK传this

3,常见解决方案

(1)将内部类定义成静态内部类,并且将外部引用采用弱引用

如Handler的正确写法

private static class MyHandler extends Handler {
private WeakReference<MyPresenter> activityWeakReference;
public MyHandler(MyPresenter activity){
activityWeakReference = new WeakReference<>(activity);
}
@Override
public void handleMessage(Message msg) {
MyPresenter activity = activityWeakReference.get();
if(activity != null) {

}
}
}
Thread的正确使用

public class MainActivity extends Activity {

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
exampleTwo();
}

private void exampleTwo() {
new MyThread().start();
}

private static class MyThread extends Thread {
@Override
public void run() {
while (true) {
SystemClock.sleep(1000);
}
}
}
}
(2)context的正确使用:
能传applicationContext的地方就传applicationContext,比如说Toast的就可以传applicationContext;对于第三方SDK也是一样,能传applicationContext就不传this。