当前位置 : 主页 > 手机开发 > android >

Android消息机制

来源:互联网 收集:自由互联 发布时间:2021-06-11
关于Android消息机制的源码分析 1.应用程序入口分析 应用程序入口是在 ActivityThread 类里 main 方法,(当应用启动后,底层通过C/C++调用main方法)。 核心代码: 1 2 3 4 5 6 7 8 9 10 11 public

关于Android消息机制的源码分析

1.应用程序入口分析

应用程序入口是在ActivityThread类里main方法,(当应用启动后,底层通过C/C++调用main方法)。

核心代码:

      
      
       
       1
      
      
      
      
       
       2
      
      
      
      
       
       3
      
      
      
      
       
       4
      
      
      
      
       
       5
      
      
      
      
       
       6
      
      
      
      
       
       7
      
      
      
      
       
       8
      
      
      
      
       
       9
      
      
      
      
       
       10
      
      
      
      
       
       11
      
      
      
      
       
       public static void (String[] args) {
      
      
      
      
       
               Environment.initForCurrentUser();
      
      
      
      
       
               EventLogger.setReporter(
       
       new EventLoggingReporter());
      
      
      
      
       
               Looper.prepareMainLooper();
      
      
      
      
       
               ActivityThread thread = 
       
       new ActivityThread();
      
      
      
      
       
               thread.attach(
       
       false);
      
      
      
              
       
       if (sMainThreadHandler == 
       
       null) {
      
      
      
      
       
                   sMainThreadHandler = thread.getHandler();
      
      
      
      
       
               }
      
      
      
      
       
               Looper.loop();
      
      
      
      
       
           }
      
      

1.1 初始化了Environment对象,然后创建了Lopper,然后开始消息循环。如果程序没有死循环,执行完main函数就会立马退出。之所以App可以一直运行是因为Looper.loop()是一个死循环。

      
      
       
       1
      
      
      
      
       
       2
      
      
      
      
       
       3
      
      
      
      
       
       4
      
      
      
      
       
       public static void loop() {
      
      
      
          
       
       for (;;) {
      
      
      
      
       
           }
      
      
      
      
       
       }
      
      

这里用for(;;)而不是while(true)是为了防止一些人通过黑科技修改这个标志位(通过反射机制)(这里不是很懂)!

在非主线程里面我们也可以创建一个Handler,但是需要我们主动去为当前的子线程绑定一个Looper,并且启动消息循环

Looper有两个核心方法:prepare()与loop()。通过Looper、Handle、Message、MessageQueue等组成了Android的消息处理机制。

2.为什么需要这样一个消息机制

2.1 不阻塞主线程

Android应用启动时,会创主线程, 负责与UI组件(widget,view)进行交互, 比如控制UI界面显示,更新等。这种单线程模型导致运行性大大降低,只能处理简单、短暂的操作。过重的任务比如下载访问数据库等都会导致ANR。Android大部分耗时操作都应该放到子线程,不要在主线程做操作

2.2 并发程序的有序性

单线程模型的UI主线程也是不安全的,会造成不可确定的结果。

线程不安全简单理解为:多线程访问资源时,有可能出现多个线程先后更改数据造成数据不一致。比如,A工作线程(也称为子线程)访问某个公共UI资源,B工作线程在某个时候也访问了该公共资源,当B线程正访问时,公共资源的属性已经被A改变了,这样B得到的结果不是所需要的的,造成了数据不一致的混乱情况。

线程安全简单理解为:当一个线程访问功能资源时,对该资源进程了保护,比如加了锁机制,当前线程在没有访问结束释放锁之前,其他线程只能等待直到释放锁才能访问,这样的线程就是安全的。

Android只允许主线程更新UI界面,子线程处理后的结果无法和主线程交互,即无法直接访问主线程,这就要用到Handler机制来解决此问题。基于Handler机制,在子线程先获得Handler对象,该对象将数据发送到主线程消息队列,主线程通过Loop循环获取消息交给Handler处理。

有了消息机制,我们可以发送消息,然后Looper把消息发给主线程,然后就可以执行了。

消息包括:

我们自己的操作消息,即客户端的Handler

操作系统的操作消息,系统的Handler,例如来电话跳出界面,就需要。

先分析系统的Handler,再去深入理解消息机制里面各个组件

3.系统的Handler

ActivityThread的成员变量有这样一个H(继承自Handler),这个就是系统的Handler。

      
      
       
       1
      
      
      
      
       
       final H mH = 
       
       new H();
      
      

回顾一下ActivityThread的初始化,在main方法中ActivityThread thread = new ActivityThread();在new的时候就已经完成了初始化成员变量,单例饿加载。

在H中定义了大量的常量,然后用case做操作。

从系统的Handler中,在handlerMessage我们可以看到四大组件的生命周期操作,创建,销毁,切换等。跨进程通信及Application进程的销毁。

比如说我们有一个 应用程序A 通过 Binder 去跨进程启动另外一个 应用程序B 的 Service(或者同一个应用程序中不同进程的Service),如图:AMS是四大组件的生命周期的一个比较重要的类,IPC机制会涉及

58e5affdc7e6c.png

最后AMS接收到消息后,发送消息到MessageQueue里面,最后由系统的Handler处理启动Service的操作:

58e5b282509cd.png

在handlerCreateService()里通过反射的方式去newInstance(),并且毁掉了Service的Oncreate方法。

58e5b2de61799.png

又例如我们可以通过发SUICIDE消息可以自杀,这样来退出应用程序。

      
      
       
       1
      
      
      
      
       
       2
      
      
      
      
       
       3
      
      
      
      
       
       case SUICIDE:
      
      
      
      
       
           Process.killProcess(Process.myPid());
      
      
      
          
       
       break;
      
      

应用程序退出

实际上我们要退出应用程序的话,就是让主线程结束,换句话说就是要让 Looper 的循环结束。这里是直接结束 Looper 循环,因此我们四大组件的生命周期方法可能就不会执行了,因为四大组件的生命周期方法就是通过 Handler 去处理的,Looper 循环都没有了,四大组件还玩毛线!因此我们平常写程序的时候就要注意了,onDestroy 方法是不一定能够回调的。

58e5b38e7a18e.png

这里实际上是调用了 MessageQueue 的 quit,清空所有 Message。

      
      
       
       1
      
      
      
      
       
       2
      
      
      
      
       
       3
      
      
      
      
       
       public void quit() {
      
      
      
      
       
           mQueue.quit(
       
       false);
      
      
      
      
       
       }
      
      

4.消息机制的分析

4.1 消息对象Message的分析

提到消息机制,在MessageQueue里面存在的就是我们Message对象。

58e5b4e08f7e6.png

Message 里面有一些我们常见的参数,arg1 arg2 obj callback when 等等。这里要提一下的就是这个 target 对象,这个对象就是发送这个消息的 Handler对象,最终这条消息也是通过这个 Handler 去处理掉的。

4.2 消息的循环过程分析

1.拿到Looper()对象(me),如果当前线程没有Looper,那么就抛出异常。这就是为什么在子线程里面创建Handler如果不手动创建启动Looper会报错的原因。

2.拿到Looper的成员变量MessageQueue,在MessageQueue里面不断地去区消息,关于MessageQueue的next用法如下:

这里可以看到消息的取出用到了一些native方法,这样做是为了获得更高的效率,消息的去取出并不是直接就从队列的头部取出的,而是根据了消息的when时间参数有关的,因为我们可以发送延时消息、也可以发送一个指定时间点的消息。因此这个函数有点复杂,我们点到为止即可。

58e5ba6c7b791.png

58e5baf15d1d6.png

3、继续分析 loop方法:如果已经没有消息了,那么就可以退出循环,那么整个应用程序就退出了。什么情况下会发生呢?还记得我们分析应用退出吗?

在 系统Handler 收到 EXIT_APPLICATION 消息的时候,就会调用 Looper 的 quit方法:

58e5bacc9d2ee.png

原文:大专栏  Android消息机制

网友评论