安卓事件分发机制详解,讲的太透彻了

文章探讨了IT从业者对职业发展和学习编程的困惑,强调兴趣和持续学习的重要性,并深入解析了UI线程和主线程的概念,指出在Android开发中,UI线程不仅限于主线程,而是与ViewRootImpl的创建相关。同时,提供了学习路径和资源推荐,鼓励长期投入和交流学习。
摘要由CSDN通过智能技术生成

前言

最近经常被朋友问到的两个问题。

问题一: “从事IT工作3年了,做技术好累啊,是不是做到30岁就不能继续往下做啊?”问题二: “我已经30岁了,还能不能学编程?”

我给出的答案是:

只要你兴趣还在,可以一直做,什么时候都不会晚;种一棵树最好的时间是十年前,其次是现在。

本人目前在 IT 行业工作了 6 年,做过大大小小的项目,虽然跟网上那些大牛比还差很远。但也确实经历过同样困惑,也迷茫过,踩过很多坑,今后也会继续踩。所以关于这一类问题,也有心得体验,在此算是做个人分享吧。

面试官:说说什么是 UI 线程?

A:就是用来刷新 UI 所在的线程嘛

面试官:多说点

A:UI 是单线程刷新的,如果多个线程可以刷新 UI 就无所谓是不是 UI 线程了,单线程的好处是,UI 框架里不需要到处上锁,做线程同步,写起来也比较简单有效

面试官:你说的这个 UI 线程,它到底是哪个线程?是主线程吗?

A:拿 Activity 来说,我们在 Activity 里异步做完耗时操作,要刷新 UI 可以调用 Activity.runOnUiThread 方法,在 UI 线程中执行,那么我们看下这个方法自然就知道 UI 线程是哪个线程了。

public final void runOnUiThread(Runnable action) {
    if (Thread.currentThread() != mUiThread) {
        mHandler.post(action);
    } else {
        action.run();
    }
}

这个方法会判断当前是不是在主线程,不是呢就通过 mHandler 抛到主线程去执行。 这个 mHandler 是 Activity 里的一个全局变量,在 Activity 创建的时候通过无参构造函数 new Handler() 一起创建了。

因为是无参,所以创建时用的哪个线程,Handler 里的 Looper 用的就是哪个线程了。创建 Activity 是在应用的主线程,因此 mHandler.post 去执行的线程也是主线程。 刚也说 了,runOnUiThread 方法里,先判断是不是在 UI 线程,这个 mUiThread 又是什么时候赋值的呢,答案还在 Activity 的源码里

final void attach(Context context, ...) {
 ...省略无关代码
 mUiThread = Thread.currentThread();
}

在 Activity.attach 方法里,我们把当前线程赋值给 mUiThread,那当前线程是什么线程呢,也是主线程。至于为什么创建 Activity 和 attach 都是主线程,那又是另外一个故事了 通过前面的分析,我们知道了,对于 Activity 来讲 UI 线程就是主线程

面试官:所以你的结论是 UI 线程就是主线程?

A:这是你说的,记住这个开发的时候不会错,但是不够准确。在子线程里刷新 UI 的时候会抛一个异常

ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.

大意是只有最初始创建 View 层级关系的线程可以 touch view,这里指的也就是 ViewRootImpl 创建时所在的线程,严格来说这个线程不一定是主线程。这一点呢,读 View.post 方法也可以得到相同的结论。所以对于 View 来说,UI 线程就是 ViewRootImpl 创建时所在的线程,Activity 的 DecorView 对应的 ViewRootImpl 是在主线程创建的

面试官:这个 ViewRootImpl 什么时候创建

A:Activity 创建好之后,应用的主线程会调用 ActivityThread.handleResumeActivity,这个方法会把 Activity 的 DecorView 添加到 WindowManger 里,就是在这个时候创建的 ViewRootImpl

面试官:那可以在异步线程刷新 View 吗?

A:刚才我们说了,只要是 ViewRootImpl 创建的线程就可以 touch view,然后 WindowManger.ad

点击领取完整开源项目《安卓学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》

dView 的时候又会去创建 ViewRootImpl,所以我们只要在子线程调用 WindowManger.addView,这个时候添加的这个 View,就只能在这个子线程刷新了,这个子线程就是这个 View 的 UI 线程了。

面试官:好,我们再聊点别的

最后

写到这里也结束了,在文章最后放上一个小小的福利,以下为小编自己在学习过程中整理出的一个学习思路及方向,从事互联网开发,最主要的是要学好技术,而学习技术是一条慢长而艰苦的道路,不能靠一时激情,也不是熬几天几夜就能学好的,必须养成平时努力学习的习惯,更加需要准确的学习方向达到有效的学习效果。
由于内容较多就只放上一个大概的大纲,需要更及详细的学习思维导图的点击这里>Android IOC架构设计免费获取。
群内还有免费的高级UI、性能优化、架构师课程、NDK、混合式开发(ReactNative+Weex)微信小程序、Flutter全方面的Android进阶实践技术资料,并且还有技术大牛一起讨论交流解决问题。

开发(ReactNative+Weex)微信小程序、Flutter全方面的Android进阶实践技术资料,并且还有技术大牛一起讨论交流解决问题。**

image

  • 14
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值