zoukankan      html  css  js  c++  java
  • 四大组件的工作过程

    一、Activity的工作过程

    从startActivity方法开始分析:

    ①、StartActivity有好几种重载方法,但是最终调用startActivityResult()方法

    ②、startActivityForResult()方法(P319 ①):

    因为看的是启动过程,所以只要看mParent == null部分即可。mParent指的是一个Fragment:被用来在一个界面中嵌入多个子Activity。

    先注意一下mMainThread.getApplicationThread()参数->返回值是一个ApplicationThread类,ApplicationThread是ActivityThread的内部类。这两个类在启动Activity十分有用。

    ③、看Instrumentation.execStartActivity()方法:

    发现启动Activity的真正实现是由ActivityManagerNative.getDefault()的startActivity()来完成的。

    来看一下ActivityManagerNative(AMN)这个类:继承自Binder并实现IActivityManager的Binder接口。(自定义重写的IActivityManager.java文件)

    ActivityManagerService(AMS)继承AMN这个类,所以AMS也是一个Binder,IActivityManager接口的实现方法在此。

    再来看看ActivityMangerNative的部分代码(P321 ①),可知,AMS这个Binder对象采用单例模式向外提供,Singleton类时单例的封装类,第一次调用get()方法的时候会调用其create()方法初始化Binder对象(根据代码从ServiceManager中返回IActivityManager对象),然后查看AMS的startActivity()方法就可以了(远程调用startActivity方法)

    (稍后讲解)

    ④、接着看一下execStartActivity()的checkStartActivityResult()(P322 ①):

    作用:检查Activity的启动结果,当无法正确启动一个Activity的时候,就会抛出异常。

    ⑤、回到AMS的startActivity()方法中(P323 ①)

    启动过程又转移到ActivitysStackSupervisor的startActivityMayWait()->startActivityLocked()->startActivityUncheckedLocked()->ActivityStack的resumeTopActivityiesLocked() 这一系列过程将启动过程转移到ActivityStack中去了。

    ⑥、ActivityStack的resumeTopActivityiesLocked()实现(P324 ①)

    resumeTopActivity调用了resumeTopActivityInnerLocked()->ActivityStackSupervisor的startSpecificActivityLocked()

    ⑦、查看ActivityStackSupervisor的startSpecificActivityLocked()实现(P324 ②)

    调用了realStartActivityLocked()

    流程图:

     ⑧、realStartActivityLocked()中有一段代码(P325 ①)

    注意app.thread这个对象是一个IApplicationThread类(p326 ①),根据分析IApplicationThread(是个Binder型接口)且 这个Binder接口的实现者完成了大量和Activity及Service启动和停止相关的功能。

    ⑨、IApplicationThread类:

    ActivityThread的内部类ApplicationThread为其实现者(P328 ①),发现该类继承了ApplicationThreadNative,ApplicationThreadNative为IApplicationThread的java类(就是自动为aidl生成的java类)。最终ApplicationThread的scheduleLaunchActivity()方法启动Activity()

    ⑩、ApplicationThread的scheduleLaunchActivity()(P329①)

    发送一个启动Acitivity的消息给Handler处理

    ⑪、接下来看看Handler对消息的处理(P331 ①)

    根据从Handler对“LAUNCH_ACTIVITY”这个消息的处理可以知道,Activity的启动过程又ActivityThread的handleLaunchActivity()方法实现

    ⑫handleLaunchActivity()

    通过performLaunchActivity()方法最终完成Activity的创建和启动,并且再通过handleResumeActivity()来调用被启动的Activity的onResume()方法

    ⑬performLaunchActivity()主要完成的事件

    1.从ActivityClientRecord中获取Activity的组件的信息(P333 ①...)

    2.通过Instrumentation的newActivity()方法使用类加载器创建Activity对象(P333 ② P334 ①)

    3.通过LoadedApk的makeApplication()方法(P334 ②)创建Application对象(一个应用只会有一个Application对象,如果已经被创建就不会创建了),发现Application对象的创建也是通过Instrumentation完成的,当Application创建完毕的话就会通过instrumentation.callApplicationOnCreate()调用Application的onCreate()方法。

    4.之后创建ComtextImp对象(P335 ①)(是Context的具体实现,重要的数据结构),通过Activity.attach()方法与Activity建立联系,同时attach()方法中完成将Activity添加进入Window的过程。

    5.最后通过mInstrumentation.callActivityOnCreate(),调用Activity.onCreate()。

    二、Service的工作过程

    Service简介:Service具有两种工作状态,一种是启动状态(执行后台计算,无法交互),一种是绑定状态(可交互,但随着Activity的消亡而消亡)。注意的是这两种状态可以共存。

    Service的启动过程

    从启动状态说起

    ①、调用ContextWrapper.startService()(P336 ① ②)

    发现调用mBase.startService()这个mBase就是ContextImpl类,就是Activity启动过程在attach()关联的对象。从mBase中看出大部分操作都是通过mBase来执行的,这种方式叫做桥接模式。

    ②、观察mBase.startService()(P337 ①)

    调用startServiceCommon方法,通过ActivityManagerNative.getDefault()方法获取AMS(Activity中提到过).然后调用其startActivity()

    ③、AMS.startActivity()方法(P338 ①)

    AMS会通过mServices这个对象,完成后续启动过程。mServices对象的类型是ActiveServices,是用来辅助AMS进行Service管理的类。

    调用ActiveServices.startServiceLocked()方法->startServiceInnerLocked()(P338 ②)

    ④、 startServiceInnerLocked()

    作用:描素一个Service的记录,把创建过程交给了bringUpServiceLocked()处理->realStartServiceLocked()

    ⑤、realStartServiceLocked()(P339 ①)

    通过app.thread的sheduleCreateService()创建Service对象并调用其onCreate,之后使用sendServiceArgsLocked()调用其余方法比如(onStartCommand)

    ⑥、查看app.thread的sheduleCreateService()(P341 ①)

    发现也是发送消息到Handler(跟Activity过程一样),之后Handler接收CREATE_SERVICE然后调用ActivityThread.handleCreateService()

    ⑦、ActivityThread.handleCreateService()(P341 ②)

    1.通过类加载器创建Service类

    2.创建Application类并调用其onCreate()

    3.创建ContextImpl通过Service.attach()建立联系

    4.调用Service的onCreate()将Service存储到ActivityThread中的一个列表中

    5.此外ActivityThread还会通过handleServiceArgs方法调用Service的onStartCommand()(P343 ①)

    Service的绑定过程

    ①、调用ContextWrapper的bindService()方法(P344 ①):

    调用mBase.bindService(mBase同样是ContetImpl类型的对象),该方法最终调用自己的bindServiceCommom()。

    ②、bindServiceCommom()(P344 ②)

    1.将ServiceConnection对象转化为ServiceDispatcher.InnerConnection对象。

    问:为什么不能直接使用ServiceConnection?

    答:因为绑定服务有可能是跨进程的(Service本身在一个进程中),所以ServiceConnection必须借助Binder才能让远程服务回调自己的方法。ServiceDispatcher的内部类InnerConnection充当了Binder这个角色。

    问:ServiceDispatcher的作用?

    连接ServiceConnection和InnerConnection的作用。

    连接过程由LoadedApk.getServiceDispatcher方法完成

    2.调用AMS的bindServiceCommon()完成Service的具体绑定过程

    ③、LoadedApk.getServiceDispatcher()(P345 ①)

    1.在上面的代码中mServices是个ArrayMap,存储了当前活动的ServiceConnection和ServiceDispatcher的映射关系。(SC为key,SD为value)

    2.系统首先会查找是否有相同的ServiceConnection,如果不存在就重新创建一个,并存储在mServices中。ServiceDispatcher内部有保存了ServiceConnection和InnerConnection对象。当Service和客户端建立连接的时候,会通过InnerConnection来调用ServiceConnection的onServiceConnected方法。(这个过程有可能是跨进程的)。当ServiceDispatcher创建完之后,getServiceDispatcher()会返回InnerConnection对象。

    ④、AMS的bindServiceCommon()(P347 ①)

    AMS调用ActivityServices的bindServiceLocked()方法->bringUpServiceLocked()->realStartServiceLocked()(该方法运行方式与Service启动过程中的realStartServiceLocked()相似)不同的是该方法中通过app.thread.scheduleBindService(Service的启动过程的方法是app.thread.scheduleCreateService);

    ⑤、app.thread.scheduleBindService()(P347 ①)

    同Service的启动过程,发送MSG:BIND_SERVICE给Handler,在Handler内部会调用ActivityThread的handleBindService()

    ⑥、ActivityThread的handleBindService()(P349 ①)

    1.通过Service的token取出Service对象

    2.调用Service的onBind()方法,返回一个binder(原则上来说,只要onBind()被调用就算绑定成功,但还要通知客户端。当多个客户端绑定同一个Service时,onBind()方法只会被调用一次,原因看代码)

    3.调用AMS.publicService()调用客户端中ServiceConnection中的onServiceConnected()方法。

    ⑦、AMS.publicService()(P;349 ②)

    将具体工作交给了ActiveServices的mServices对象的publishServiceLocked->c.conn.connected()

    c.conn表示:ServiceDispatcher.InnerConnection

    ⑧、研究一下ServiceDispatcher.InnerConnection类(P350 ①)

    调用了ServiceDispatcher的connected()方法

    ⑨、ServiceDispatcher的connected()(P350 ②)

    调用mActivityThread.post(new RunConnection(name,service,0));

    作用:让RunnConnection运行在主线程中

    mActivityThread表示ActivityThread的Handler。

    RunConnection类代表一个Runnable

    ⑩查看RunConnection类(P351 ①)

    作用:判断Service死亡还是绑定,选择调用ServiceDispatcher的doConnected()还是doDeath()

    ⑪ServiceDispatcher的doConnected():调用ServiceConnection.onServiceConnected()方法

     BroadcastReceiver的工作过程

     一、简单使用复习

    ①、添加一个BroadcastReceiver(详见:BroadcastReceiver浅析)

    //创建类继承BroadcastReceiver类
    public class MyReceiver extends BroadcastRecevier{
       public void receiver(Intent intent){
          //输入代码 
       }
    }    
    
    
    //在AndroidMaintest.xml中注册
    <Recevier android:name=".MyReceiver">
      <intent-filter>
         <action android:name="com.chen.receiver.LAUNCH"/>
      </intent-filter>    
    </Receiver>
    
    //在代码中注册
    MyReceiver myRecevier = new MyReceiver();
    IntentFilter intentFilter = new IntentFilter();
    intentFilter.addAction("com.chen.receiver,LAUNCH");
    registerReceiver(myRecevier,intentFilter);
    
    //注意当用代码注册的时候需要在合适的地方接触注册
    unRegisterReceiver(myRecevier);
    
    //启动BroadcastRecevier
    Intent intent = new Intent();
    intent.addAction("com.chen.recevier.LAUNCH");
    sendBroadcastRecevier(intent);
    Broadcast的简单使用

    二、广播的注册过程(动态注册)

    ①、从registerReceiver()开始->跟Service调用方法一样交给ConextImpl.registerReceiver()->调用了自己的registerReceiverInternal()

    ②、ConextImpl.registerReceiverInternal()(P353 ①)

    1.如果mPackageInfo存在则获取IIntentReceiver,不存在则创建IIntentReceiver

    2.IntentRecevier作用:因为BroadcastRecevier是组件无法跨继承,所以产生IIntentReceiver包装BoradcastReceiver实现跨进程,向AMS发送广播注册消息。IIntentReceiver是一个Binder接口,具体实现在LoadApk.RecevierDispatcher.InnerReceiver,ReceiverDispatcher内部同时保存了BroadcastReceiver和InnerRecevier,这样当接口到广播的时候,很容易调用BraodcastRecevier的receive()方法。(发现与Service的原理相似)

    3.创建IIntentReceiver过程:调用ReceiverDispathcer.getIIntentReceiver()(P355 ①)

    如果该BroadcastRecevier未已被注册,则重新创建一个ReceiverDispatcher对象并保存BroadcastReceiver对象,将IIntentReciever对象作为返回值。

    4.最终注册过程是由AMS的registReceiver()方法完成的(P355 ②)

    最终会把InnerRecevier对象和IntentFilter对象存储起来,这样注册过程就完成了

    三、发送和接收过程(普通广播)

    ①.调用sendBroadcast()->调用ContextImpl.sendBroadcast()->调用AMS.broadcastIntent() 直接向AMS发起异步请求用于发送广播

    ②、AMS.broadcastIntent()(P357 ①)

    调用broadcastIntentLocked()

    ③、AMS.broadcastIntent() (P357 ②   P358 ①)

    作用1:控制广播是否要对已停止的BroadcastReceiver起作用 ,默认是不起作用的

    作用2:根据intent-fileter查找出匹配的广播接收者,最终将满足的广播接收者添加到BroadcastQueue中,接着BroadcastQueue就会将广播发送给相应的广播接收者。

    ④、查看BroadcastQueue的发送过程(P359 ①)

    发现发送给Handler一条BROADCAST_INTENT_MSG的消息,当BroadcastQueue收到消息会调用processNextBroadcast()

    ⑤、processNextBroadcast()(P359 ②)

    发现无序广播存储在mParallelBroadcasts对象中,之后遍历该对象,调用deliverToRegisteredReceiverLocked()->内部调用了performReceiverLocked()完成具体过程

    ⑥、performReceiverLocked()(P360 ①)

    调用app.thread(ApplicationThread)的scheduleRegisteredReceiver()

    ⑦、app.thread.scheduleRegisteredReceiver()(P361 ①)

    调用InnerReceiver.performReceiver()->调用LoadedApk.ReceiverDispatcher.performReceiver()

    ⑧、LoadedApk.ReceiverDispatcher.performReceiver() (P361 ②)

    创建一个Args(Runnable类),之后通过app.thread.post(Args),将其放到主线程中,等待调用

    ⑨、查看一下Args.run()方法(P382 ①)

    发现调用了mBroadcast.recevier()方法

    ContentProvider的工作过程(暂时放弃,因为连ContentProvider的使用还没弄清楚 P362)

  • 相关阅读:
    docker compose 配置 redis cluster jenkins
    Spring Core
    Java Case Interview two
    pytest 生成 allure报告(含4要素的对应版本,兼容)
    python中requests库的post请求 4种类型参数
    接口测试流程
    Docker学习篇 搭建jenkins
    Pytest入门 实例
    python selenium css定位6种
    python selenium select标签的下拉框和非select标签的下拉框
  • 原文地址:https://www.cnblogs.com/rookiechen/p/5462595.html
Copyright © 2011-2022 走看看