2024年安卓最新LeakCanary源码学习一:常见内存泄漏分析,面试官如何提问面试者

最后

想要了解更多关于大厂面试的同学可以点赞支持一下,除此之外,我也分享一些优质资源,包括:Android学习PDF+架构视频+源码笔记高级架构技术进阶脑图、Android开发面试专题资料,高级进阶架构资料 这几块的内容。非常适合近期有面试和想在技术道路上继续精进的朋友。

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

}

在这种写法里,非静态内部类NonStaticClass 会默认持有外部类StaticLeakActivity 的引用,而非静态内部类NonStaticClass又创建了一个静态实例mResource ,而这个mResource 的生命周期和APP的生命周期是一致的,这就导致StaticLeakActivity 无法被回收,从而造成内存泄漏。

正确写法:

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 void 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造成的内存泄漏

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

总结

其实客户端开发的知识点就那么多,面试问来问去还是那么点东西。所以面试没有其他的诀窍,只看你对这些知识点准备的充分程度。so,出去面试时先看看自己复习到了哪个阶段就好。

Android大厂面试真题全套解析

2017-2020字节跳动Android面试真题解析PDF
然而Android架构学习进阶是一条漫长而艰苦的道路,不能靠一时激情,更不是熬几天几夜就能学好的,必须养成平时努力学习的习惯。所以:贵在坚持!

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

看看自己复习到了哪个阶段就好。

[外链图片转存中…(img-mmqt5ChW-1715817042878)]

[外链图片转存中…(img-ys8SnFHa-1715817042879)]
然而Android架构学习进阶是一条漫长而艰苦的道路,不能靠一时激情,更不是熬几天几夜就能学好的,必须养成平时努力学习的习惯。所以:贵在坚持!

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值