0
点赞
收藏
分享

微信扫一扫

LeakCanary源码学习一:常见内存泄漏分析,移动开发者社区

在觉 2022-01-10 阅读 29

正确写法:

public class StaticLeakActivity extends AppCompatActivity {

private static NonStaticClass mResource = null;

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_static_leak);

if (mResource == null) {

mResource = new NonStaticClass();

}

}

private static class NonStaticClass {

}

}

只需要把内部类改为static就行了,这样它就不会持有外部类StaticLeakActivity的引用,这样StaticLeakActivity的内存就可以被顺利回收。

3、Handler造成的内存泄漏

================

Handler造成的内存泄漏是非常常见的,因为使用的多。

错误写法:

public class HandlerLeakActivity extends AppCompatActivity {

private final Handler mLeakHandler = new Handler() {

@Override

public void handleMessage(Message msg) {

super.handleMessage(msg);

}

};

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_handler_leak);

mLeakHandler.postDelayed(new Runnable() {

@Override

public void run() {

}

},10006010);

finish();

}

}

分析:Handler是一个TLS变量,意思就是说它的生命周期和HandlerLeakActivity 的生命周期是不一样的,这样就可能导致内存泄漏。以上代码中,我们使用mLeakHandler发送了一个延时任务,同时finish掉HandlerLeakActivity,由于执行延时任务的message还存在于主线程中,它就会持有HandlerLeakActivity中的mLeakHandler的引用(message持有mLeakHandler的引用,mLeakHandler又持有HandlerLeakActivity的引用),这种情况下finish,HandlerLeakActivity是不会被回收的。

那么,解决办法是什么呢?

1、将Handler的声明变为静态的

2、通过弱引用的方式引入Activity

3、在activity的onDestory方法中调用handler.removeCallback()

参考文章:使用Handler容易产生的内存泄露以及介绍下Java的4种引用

正确写法:

public class HandlerLeakActivity extends AppCompatActivity {

private static class MyHandler extends Handler {

private final WeakReference mActivity;

public MyHandler(HandlerLeakActivity activity) {

mActivity = new WeakReference(activity);

}

@Override

public void handleMessage(Message msg) {

HandlerLeakActivity activity = mActivity.get();

if (activity != null) {

//…

}

}

}

private final MyHandler myHandler = new MyHandler(this);

private static final Runnable mRunnable = new Runnable() {

@Override

public void run() {

}

};

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_handler_leak);

myHandler.postDelayed(mRunnable, 1000 * 60 * 10);

finish();

}

@Override

protected void onDestroy() {

super.onDestroy();

myHandler.removeCallbacks(mRunnable);

}

}

4、线程造成的内存泄漏

===========

public class ThreadLeakActivity extends AppCompatActivity {

@Override

protected v
oid onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_thread_leak);

testThreadLeak();

}

private void testThreadLeak() {

new AsyncTask<Void, Void, Void>() {

@Override

protected Void doInBackground(Void… params) {

SystemClock.sleep(10000);

return null;

}

}.execute();

new Thread(new Runnable() {

@Override

public void run() {

SystemClock.sleep(10000);

}

}).start();

}

static class MyAsyncTask extends AsyncTask<Void, Void, Void> {

private WeakReference weakReference;

public MyAsyncTask(Context context) {

weakReference = new WeakReference<>(context);

}

@Override

protected Void doInBackground(Void… voids) {

SystemClock.sleep(10000);

return null;

}

@Override

protected void onPostExecute(Void aVoid) {

super.onPostExecute(aVoid);

ThreadLeakActivity activity = (ThreadLeakActivity) weakReference.get();

if (activity != null) {

}

}

}

static class MyRunnable implements Runnable{

@Override

public void run() {

SystemClock.sleep(10000);

}

}

}

方法testThreadLeak()里面的写法会造成内存泄漏,解决办法就是创建静态内部类。

5、WebView造成的内存泄漏

================

public class WebviewLeakActivity extends AppCompatActivity {

dLeakActivity) weakReference.get();

if (activity != null) {

}

}

}

static class MyRunnable implements Runnable{

@Override

public void run() {

SystemClock.sleep(10000);

}

}

}

方法testThreadLeak()里面的写法会造成内存泄漏,解决办法就是创建静态内部类。

5、WebView造成的内存泄漏

================

public class WebviewLeakActivity extends AppCompatActivity {

举报

相关推荐

0 条评论