美文网首页
一切从android的handler说起(六)之四大组件生命周期

一切从android的handler说起(六)之四大组件生命周期

作者: hxiao1983 | 来源:发表于2019-08-17 19:03 被阅读0次

阅读本文大概需要 4 分钟。

上一篇,我们了解到Android里触摸事件是如何一步一步转入UI线程的message queue里被执行的,这种事件是由外部事件触发的。

我接着对小张说:其实Android里还有一种UI queue里的事件更为大家熟知,你天天写代码都在与之打交道,你知道吗?

小张有些丈二和尚摸不着头脑,想了一会儿问道:能给一些提示吗?

我提示道:它是Android系统框架层产生的事件,你在四大组件上写的代码均无法逃脱它的掌控!

小张虽然不是很清楚为什么,但是由于提示太明显,问道:你说的难道是四大组件的生命周期?

我肯定道:没错,比如你天天写Activity,在其onCreate, onResume等生命周期里写业务代码,那你知道四大组件的生命周期是怎么来的吗?

小张怀疑到:难道它们也是handler消息机制触发的吗?

我说道:你没有听错!就连四大组件的生命周期也遵循了这个事件驱动模型,它们均是由Android系统框架层产生相应的message扔进UI queue触发的。

小张紧接着问道:如果这样的话,UI线程里必然存在一个handler在处理对应的message,以辨别这个message是哪个组件,是什么生命周期阶段。

我点了点头,道:你说得没错!你在Android源码里见过这个handler吗?

小张摇了摇头:我平时业务做得比较多,对Android系统框架层的源码看得比较少。

我听了后说道:那你平时可得多关注关注一些底层原理类的东西了,业务是永远在变动,而越是底层的东西越是相对稳定的,只有弄清楚基础才能知其所以然,更好的为业务服务。

小张听后,连忙点头:你说得是,回去一定恶补这块短板。

我继续说道:好了,Android源码里有个ActivityThread内部类H就是刚才所说的handler了,你看看它的源码,你就知道它都在干些什么了。

1private final class H extends Handler {

2    ...

3    public void handleMessage(Message msg) {

4            if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + msg.what);

5

6              switch (msg.what) {

7

8                case LAUNCH_ACTIVITY: {

9                    ActivityClientRecord r = (ActivityClientRecord)msg.obj;

10                    r.packageInfo = getPackageInfoNoCheck(r.activityInfo.applicationInfo);

11                    handleLaunchActivity(r, null);

12                } 

13                    break;

14

15                case RELAUNCH_ACTIVITY: {

16                    ActivityClientRecord r = (ActivityClientRecord)msg.obj;

17                    handleRelaunchActivity(r);

18                } 

19                    break;

20

21                case PAUSE_ACTIVITY:

22                    handlePauseActivity((IBinder)msg.obj, false, msg.arg1 != 0, msg.arg2);

23                    maybeSnapshot();

24                    break;

25

26                case PAUSE_ACTIVITY_FINISHING:

27                    handlePauseActivity((IBinder)msg.obj, true, msg.arg1 != 0, msg.arg2);

28                    break;

29

30                case STOP_ACTIVITY_SHOW:

31                    handleStopActivity((IBinder)msg.obj, true, msg.arg2);

32                    break;

33

34                case STOP_ACTIVITY_HIDE:

35                    handleStopActivity((IBinder)msg.obj, false, msg.arg2);

36                    break;

37                    ...

38                case RESUME_ACTIVITY:

39                    handleResumeActivity((IBinder)msg.obj, true, msg.arg1 != 0);

40                    break;

41                case SEND_RESULT:

42                    handleSendResult((ResultData)msg.obj);

43                    break;

44                case DESTROY_ACTIVITY:

45                    handleDestroyActivity((IBinder)msg.obj, msg.arg1 != 0,msg.arg2, false);

46                    break;

47                    ...

48                case NEW_INTENT:

49                    handleNewIntent((NewIntentData)msg.obj);

50                    break;

51                case RECEIVER:

52                    handleReceiver((ReceiverData)msg.obj);

53                    maybeSnapshot();

54                    break;

55                case CREATE_SERVICE:

56                    handleCreateService((CreateServiceData)msg.obj);

57                    break;

58                case BIND_SERVICE:

59                    handleBindService((BindServiceData)msg.obj);

60                    break;

61                case UNBIND_SERVICE:

62                    handleUnbindService((BindServiceData)msg.obj);

63                    break;

64                    ...

65                case STOP_SERVICE:

66                    handleStopService((IBinder)msg.obj);

67                    maybeSnapshot();

68                    break;

69                    ...

70            }

71            if (DEBUG_MESSAGES) Slog.v(TAG, "<<< done: " + msg.what);

72        }

73        ...

74}

从上面的代码,我们可以清晰的看到四大组件的生命周期函数调用赫然在列!

小张看了代码后发问了:我看到Activity生命周期相应的每个msg.obj前面都用了IBinder进行了强转,是不是说明这些message都不是App自己进程里产生扔过来的?

我笑道:你的眼力不错嘛。这就问到message的事件来源问题了,你说的不错,你平时打开一个Activity都有哪些方式?

小张说道:要么显示,要么隐式的startActivity。

我继续问道:嗯,那你知道这个过程大概是怎么样的吗?

小张说道:这个我知道,用户App会通过Binder IPC通信询问AMS(ActivityManagerService),向其索要满足条件的Activity。

我说道:没错,我们知道AMS是在系统的SystemServer进程中,统管Android上的所有Activity(这又是典型解耦手段--集中管理的HUB思想)。当找到了对应的Activity之后,由于跨进程,就通过Binder IPC手段来通知用户App进程所在的UI线程来打开对应的Activity。

小张接道:所以,AMS就把这种意图打包进message里,通过Binder IPC扔进UI线程的message queue中[注],当UI线程唤醒时,取出message交由H实例handler处理时,就进入了上述代码的switch case分支,发现了是LAUNCH_ACTIVITY,就调用handleLaunchActivity处理逻辑,其中就嵌入了Activity的onCreate, onStart调用,预留给开发者重写具体的业务逻辑。

我哈哈笑道:你都学会抢答了,进步很快啊,孺子可教也。所以你看,为什么平时说在UI线程的生命周期做繁重的耗时任务会导致UI卡顿或者ANR?

小张答道:由于任何UI线程的业务代码均逃离不了组件的生命周期,而生命周期又源于UI queue中的message的处理,所以如果在任何一个生命周期做了耗时任务,这会导致queue中后面的message无法得到及时的处理,所以看起来就是有反应延时,也就是视觉上的卡顿,严重的会长时间得不到处理,从而导致ANR的发生。

我肯定的点了点头:你看,底层原理一通百通,平时Android开发时要遵循的在这里得到了真实的解答,是不是感觉理解更加深刻了?

小张兴奋的说道:是啊,知道了为什么之后,感觉有种入木三分的感觉,以后在开发中就绝对不会犯这样的错误了。

最后我又继续补充道:其实这其中也蕴含了一种设计思想。当你想设计一套底层框架系统,而且又希望上层应用遵循你的规则,就需要预留这样的接口或者抽象函数,以供开发者来具体实现。

小张说道:这就是依赖倒置思想吧?

我说道:是的。其实Android系统源码里有大量的设计模式的运用,有机会可以好好看看。

小张:嗯,看来底层原理还挺有意思的,弄懂后还能加强对上层应用的理解,真是非常有必要系统性的学习了。

[注]:这里AMS其实并不是和UI线程直接打交道,而是通过App端的Binder线程,然后再传递给UI线程。如下图:

有热爱Android技术的同学,欢迎加微信公众号 xh18310039919。用诙谐的方式学习Android硬核知识点。

相关文章

网友评论

      本文标题:一切从android的handler说起(六)之四大组件生命周期

      本文链接:https://www.haomeiwen.com/subject/myvksctx.html