美文网首页
Android Framework系列5-1 Activity启

Android Framework系列5-1 Activity启

作者: 无为3 | 来源:发表于2021-03-04 11:21 被阅读0次

    Android Activity

    本章主要围绕以下几点讲解:

    • Activity冷启动原理
    • 启动过程中涉及的组件及通信原理
    • 启动过程中的生命周期回调原理

    Activity冷启动原理

    先从启动的入口函数看起:startActivity

    // 代码来自Android23中:ContextImpl.java
    public void startActivity(...){
          mMainThread.getInstrumentation().execStartActivity(...);
    }
    
    // 代码来自Android23中:Instrumentation.java
    public ActivityResult execStartActivity(...){
          ActivityManagerNative.getDefault().startActivity(...);
    }
    

    跨进程调用,先通过ActivityManagerNative.getDefault()拿到AMS的代理对象(ActivityManagerProxy),调用它的startActivity()。

    // 代码来自Android23中:ActivityManagerNative.java
    class ActivityManagerProxy implements IActivityManager{
          public int startActivity(...){
                mRemote.transact(START_ACTIVITY_TRANSACTION, data, reply, 0);
          }
    }
    
    • 把所有的请求参数都封装到一个Parcel里面(参数data)
    • 然后写到binder驱动,binder驱动再转发到AMS。
    • 这样AMS就能收到一个onTransact回调。
    // 代码来自Android23中:ActivityManagerNative.java
    public abstract class ActivityManagerNative{
          @Override
        public boolean onTransact(int code, Parcel data, Parcel reply, int flags){
              switch (code) {
            case START_ACTIVITY_TRANSACTION: {
                  int result = startActivity(......)
            } 
            ......
        }
    }
    

    现在着重看下AMS中怎么处理startActivity的,有点绕,我们就直接看关键的函数:

    // 代码来自Android23中:ActivityStackSupervisor.java
    void startSpecificActivityLocked(ActivityRecord r,...){
          ProcessRecord app = mService.getProcessRecordLocked(...);
          if (app != null && app.thread != null) {
              realStartActivityLocked(r, app, andResume, checkConfig);
              return;
          }
          mService.startProcessLocked(r.processName...)
    }
    

    看过我们前面章节的同学看到这块代码应该挺熟悉的,应用进程启动

    • 查询Activity所属进程是否启动,也就是ProcessRecord对象不为空且应该用进程向AMS注册过IApplicationThread(app != null && app.thread != null)
    • 如果上述条件成立,则直接启动Activity。
    • 不成立再去启动进程。

    进程启动
    对startProcessLocked(进程启动)这个函数之前未做详细介绍,现在看看如何启动进程的:

    // 代码来自Android23中:ActivityServiceManager.java
    private final void startProcessLocked(ProcessRecord app,....){
          if (entryPoint == null) entryPoint = "android.app.ActivityThread";
          Process.ProcessStartResult startResult = Process.start(entryPoint, );
          synchronized (mPidsSelfLocked) {
              mPidsSelfLocked.put(startResult.pid, app);
              Message msg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
              msg.obj = app;
              mHandler.sendMessageDelayed(msg, PROC_START_TIMEOUT);
          }
    }
    
    • entryPoint这个就是应用进程启动之后,它的入口函数的java类。
    • Process.start这个会向Zygote发送一个启动进程的请求,会把entryPoint带上,这样当Zygote启动进程后会知道启动那个java类的入口函数。
    • 进程启动会返回ProcessStartResult,其中有进程的pid。
    • 把进程app添加到mPidsSelfLocked(SparseArray类型),key为进程id。
    • 延迟发送一个消息,代表应用进程启动之后在一定时间内(10秒内),没向AMS报告的话,就会超时,超时后AMS就会清理这个应用的所有信息。

    继续深入看看Process.start做了什么事:

    // 代码来自Android23中:Process.java
    public static final ProcessStartResult start(...){
          return startViaZygote(...);
    }
    
    // 代码来自Android23中:Process.java
     ProcessStartResult startViaZygote(final String processClass,) {
          return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi), argsForZygote);
    }
    

    startViaZygote这个函数做了两件事:

    • 打开通往Zygote的Socket(通过openZygoteSocketIfNeeded)。
    • 再通过socket发送启动进程的参数,然后读取返回结果(zygoteSendArgsAndGetResult)。

    Zygote端的处理:
    AMS向Zygote发送了socket消息,Zygote端如何处理呢?,具体看 应用进程启动 中的runOnce函数

    应用进程启动.png



    Activity启动
    前面讲到了,startActivity时如果进程未启动时是怎么启动进程的,现在来讲讲如果进程已经启动了,是怎么启动Activity的?还是看下关键函数:

    // 代码来自Android23中:ActivityStackSupervisor.java
    boolean attachApplicationLocked(ProcessRecord app){
          ActivityRecord hr = stack.topRunningActivityLocked(null);
          ......
          realStartActivityLocked(hr, app, true, true);
    }
    
    • 应用进程启动后,会去处理之前挂起的组件,Activity组件处理关键就是上面的attachApplicationLocked函数。
    • stack是mFocusedStack:在AMS中有两个stack,一个是launcher的stack(跟桌面相关);还有一个就是非launcher的stack(mFocusedStack),我们应用的task都归mFocusedStack管。
    • 拿到stack后会调用topRunningActivityLocked函数,找到最近的task取出栈顶的Activity,也就是我们要启动的Activity。
    • realStartActivityLocked启动该Activity。

    接着看下realStartActivityLocked函数:

    // 代码来自Android23中:ActivityStackSupervisor.java
    final boolean realStartActivityLocked(ActivityRecord r,...){
          app.thread.scheduleLaunchActivity(...);
    }
    

    其中app就是ProcessRecord,thread就是应用端向AMS注册的binder句柄(IApplicationThread);scheduleLaunchActivity方法也就是在应用端ActivityTread中。

    // 代码来自Android23中:ActivityThread.java
    public final void scheduleLaunchActivity(...){
          ActivityClientRecord r = new ActivityClientRecord();
          ......
          sendMessage(H.LAUNCH_ACTIVITY, r);
    }
    
    // 代码来自Android23中:ActivityThread.java
    public void handleMessage(Message msg) {
          switch (msg.what) {
              case LAUNCH_ACTIVITY: {
                  final ActivityClientRecord r = (ActivityClientRecord) msg.obj;
                  r.packageInfo = getPackageInfoNoCheck(.....);
                  handleLaunchActivity(r, null);
               } break;
              ......
    }
    
    // 代码来自Android23中:ActivityThread.java
    private void handleLaunchActivity(ActivityClientRecord r,......){
          Activity a = performLaunchActivity(r, customIntent);
          ......
          if (a != null) {
              handleResumeActivity(r.token,......);
          }
    }
    
    • 封装了一个启动Activity的消息,丢到主线程中。
    • handler怎么处理消息呢:getPackageInfoNoCheck获取一个LoadedApk对象(应用的安装信息,之后创建activity需要用到ClassLoader去加载Apk中的Activity类)。
    • 接下来就调用handleLaunchActivity,开始创建Activity生命周期。主要是两部分performLaunchActivity和handleResumeActivity。

    handleResumeActivity这里就是调用了activity的onResume生命周期;再看看看看performLaunchActivity做了啥:

    // 代码来自Android23中:ActivityThread.java
     private Activity performLaunchActivity(ActivityClientRecord r, ...) {
          Activity activity = mInstrumentation.newActivity(...);
    
          Application app = r.packageInfo.makeApplication(false, mInstrumentation);
    
          Context appContext = createBaseContextForActivity(r, activity);
          activity.attach(appContext, ...);
    
          mInstrumentation.callActivityOnCreate(activity, r.state);
          activity.performStart();
    
          return activity;
    }
    
    • 先创建了一个Activity对象(也是通过ClassLoader newInstance)
    • 创建Application(这个Application其实在进程启动后已经创建好了,这里只是返回这个Application对象)。
    • 创建上下文Context,createBaseContextForActivity这里其实就是new了一个ContextImpl对象。
    • activity.attach 把context赋给activity,也就是给activity创建了上下文。
    • callActivityOnCreate其实就是调到了activity的onCreate生命周期回调。
    • performStart其实就是调到了activity的onStart生命周期回调。

    在应用端Activity启动流程总结:


    Activity启动

    总结

    总结

    相关文章

      网友评论

          本文标题:Android Framework系列5-1 Activity启

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