安卓开发面试题(8/30)消息机制全解析(下)

牛客高级系列专栏:

安卓(安卓系统开发也要掌握)


嵌入式


本人是2020年毕业于广东工业大学研究生:许乔丹,有国内大厂CVTE和世界500强企业安卓开发经验,该专栏整理本人对常见安卓高频开发面试题的理解;

网上安卓资料千千万,笔者将继续维护专栏,一杯奶茶价格不止提供答案解析,承诺提供专栏内容免费技术答疑,直接咨询即可。助您提高安卓面试准备效率,为您面试保驾护航!

正文开始⬇

3、一问一答:常见问题汇总

经过上面的学习,到了最激动人心的时刻了,揭秘下Handler常见的问题都如何回答。一开始觉得不知道如何回答的问题,你现在一定能轻松理解

3.1 Handler 引起的内存泄露原因以及最佳解决方案

因为Handler一般是作为Activity的内部类,可以发送延迟执行的消息,如果在延迟阶段,我们把Activity关掉,此时因为该Activity还被Handler这个内部类所持有,导致Activity无法被回收,没有真正退出并释放相关资源,因此就造成内存泄漏。

工程上常用的方法是将 Handler 定义成静态的内部类,在内部持有 Activity 的弱引用,并在Acitivity的onDestroy()中调用handler.removeCallbacksAndMessages(null)及时移除所有消息。如果和面试官说了这两个方法,那你就100分过关了,但更进一步是建议将Handler抽离出来作为BaseHandler,然后每个Activity需要用到Handler的时候,就去继承BaseHandler。最佳解决方案具体代码:

// 这个是BaseHandler
public abstract class BaseHandler<T> extends Handler {
    private final WeakReference<T> mWeakReference; //弱引用

    protected BaseHandler(T t) {
        mWeakReference = new WeakReference<T>(t);
    }

    protected abstract void handleMessage(T t, Message msg);

    @Override
    public void handleMessage(Message msg) {
        super.handleMessage(msg);
        if (mWeakReference == null) {
            return;
        }

        T t = mWeakReference.get();
        if (t != null) {
            handleMessage(t, msg);
        }
    }
}

//然后在某个Activity中使用
 private static class H extends BaseHandler<XuruiActivity> { //静态的内部类哦
       
        public H(XuruiActivity activity) {
            super(activity);
        }

        @Override
        protected void handleMessage(XuruiActivity activity, Message msg) {
            //do something
        }
    }
//同时Activity的onDestroy函数取消掉所有消息
@Override
protected void onDestroy() {
    mMyHandler.removeCallbacksAndMessages(null);
    super.onDestroy();
}

3.2 为什么我们能在主线程直接使用 Handler,而不需要创建 Looper ?

详情对应2.1小节,ActivityThread是主线程操作的管理者,在 ActivityThread.main() 方法中调用了 Looper.prepareMainLooper() ,该方法调用prepare()创建Looper。因此主线程不是不需要创建Looper,而是系统帮我们做了。

3.3 Handler、Thread和HandlerThread的差别

又是这种考区别的题目,不过还算是比较常见的三个知识点:

  1. Handler:本文所学的知识,是Android的一种异步消息机制,负责发送和处理消息,可实现子线程和主线程的消息通讯;

  2. Thread:Java的一个多线程类,是Java进程中最小执行运算单位,用于给子类继承,创建线程/

  3. HandlerThread:从名字看就知道是由前面两者结合起来的。可以理解为“一个继承自Thread的Handler类”,因此本质上和父类一样是Thread,但其内部直接实现了Looper,我们可以直接在HandlerThread里面直接使用Handler消息机制。减少了手动调用Looper.prepare()和Looper.loop()这些方法。

3.4 子线程中怎么使用 Handler?

这个题目就可以结合上面两个题目来拓展理解了。子线程中使用 Handler 需要先执行两个操作:Looper.prepare() 和 Looper.loop(),看到这里你应该要记得这两个函数执行顺序是不能变的哦。同时可以直接使用HandlerThread类即可。

3.5 为什么在子线程中创建 Handler 会抛异常?

不能在还没有调用 Looper

剩余60%内容,订阅专栏后可继续查看/也可单篇购买

Android高频面试题全解析 文章被收录于专栏

#提供免费售后答疑!!花一杯奶茶的钱获得安卓面试答疑服务,稳赚不赔# Android发展已经很多年,安卓资料网上千千万,本专栏免费提供专栏内容技术答疑!!私聊当天必回。在阅读过程或者其他安卓学习过程有疑问,都非常欢迎私聊交流。

全部评论
View.post 和 Handler.post 的区别? 可以补充一下吗?
点赞 回复 分享
发布于 03-18 21:59 北京

相关推荐

VirtualBool:都去逗他了?
点赞 评论 收藏
分享
点赞 评论 收藏
分享
评论
11
7
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务