Activity 启动流程

195 阅读4分钟

这儿分析ActivityThread Main函数后的流程

ActivityThread.main()(代码只抓主线)

1 应用启动的入口

public static void main(String[] args) {
    Looper.prepareMainLooper();#UI线程Looper的启动
    .....
    ActivityThread thread = new ActivityThread();
    thread.attach(false, startSeq);#* 
    if (sMainThreadHandler == null) {
        sMainThreadHandler = thread.getHandler();
    }
    ....
    Looper.loop();
}

2 attach()

 private void attach(boolean system, long startSeq) {
     # startSeq ActivityManager 信息传递标志
     if(!system){#我们分析的分支 非系统应用
        final IActivityManager mgr = ActivityManager.getService();
        try {
            # 这个头部声明并初始化 final ApplicationThread mAppThread = new ApplicationThread();
            # IApplicationThread.Stub 接口 接收来之ActivityManager 所有信息
            # 如bindApplication
            mgr.attachApplication(mAppThread, startSeq);
        } catch (RemoteException ex) {
            throw ex.rethrowFromSystemServer();
        } 
     }else{
         ...
     }
 }

建立完通信进制开始处理接收来自ActivityManager流程指令

1、bindApplication

  public final void bindApplication(String processName, ApplicationInfo appInfo,...){
    ....
    AppBindData data = new AppBindData();
    data.processName = processName;
    data.appInfo = appInfo;
    data.providers = providers;
    data.instrumentationName = instrumentationName;
    data.instrumentationArgs = instrumentationArgs;
    data.instrumentationWatcher = instrumentationWatcher;
    data.instrumentationUiAutomationConnection instrumentationUiConnection;
    data.debugMode = debugMode;
    data.enableBinderTracking = enableBinderTracking;
    data.trackAllocation = trackAllocation;
    data.restrictedBackupMode = isRestrictedBackupMode;
    data.persistent = persistent;
    data.config = config;
    data.compatInfo = compatInfo;
    data.initProfilerInfo = profilerInfo;
    data.buildSerial = buildSerial;
    data.autofillCompatibilityEnabled autofillCompatibilityEnabled;
    sendMessage(H.BIND_APPLICATION, data);# 由 mH handler 处理  
  }

找到H handler 中 case BIND_APPLICATION: handleBindApplication(data);分支

handleBindApplication(data)

 private void handleBindApplication(AppBindData data) {
     ....

     app = data.info.makeApplication(data.restrictedBackupMode,null);# 1 application 和context 在这初始化,
     
    mInstrumentation.callApplicationOnCreate(app);#调用Application OnCreate
 }

至此绑定Application流程,当然我省略了我不懂或者我还没研究透的 接下来时启动Activity 在android28 之前ApplicationThread中的handlerLaunchActivity,不过在这之后改成事务启动,所有Activity几个重要流程都通过

@Override
 public void scheduleTransaction(ClientTransacttransaction) throws  RemoteException {
     ActivityThread.this.scheduleTransaction(transaction);
 }

最终也由 H handler处理

  case EXECUTE_TRANSACTION:
     final ClientTransaction transaction = (ClientTransaction) msg.obj;
     mTransactionExecutor.execute(transaction);
    ....
     break;

这儿简单的说明启动handlerActivity的流程

TransactionExecutor.execute()-> executeLifecycleState(transaction)-> lifecycleItem.execute(mTransactionHandler, token, mPendingActions)->LaunchActivityItem.execute()->ActivityThread.handleLaunchActivity()

2、 handleLaunchActivity()

 public Activity handleLaunchActivity(ActivityClientRecord r,
    PendingTransactionActions pendingActions, Intent customIntent) {
    final Activity a = performLaunchActivity(r, customIntent); #1   
}
1
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
    ContextImpl appContext = createBaseContextForActivity(r);
    activity = mInstrumentation.newActivity(cl, component.getClassName(), r.intent);
    
    activity.attach(appContext, this, getInstrumentation(), r.token,
            r.ident, app, r.intent, r.activityInfo, title, r.parent,
            r.embeddedID, r.lastNonConfigurationInstances, config,
            r.referrer, r.voiceInteractor, window, r.configCallback);
            
      mInstrumentation.callActivityOnCreate(activity, r.state);
      #调用Activity onCreate
}

通handleLaunchActivity 一样接下来 ApplicationThread 会收到handleStartActivity()、handleResumeActivity()、handlePauseActivity()、handleStopActivity()、handleDestroyActivity()...

应用启动大致流程分析到这儿。

下面分析Activity的界面 PhoneWindow,DecorView,ViewRootImpl 的关系(现在也说不清)

还是在上文的基础上继续分析下去

PhoneWindow的创建

handleLaunchActivity()这个方法里比较重要的两点一个是我们一直都在使用的onCreate()的调用,在这个之前attach这个方法更为重要

 final void attach(Context context, ActivityThread aThread,...){
     attachBaseContext(context);#Activity context
     mWindow = new PhoneWindow(this, window, activityConfigCallback);
     mWindow.setWindowControllerCallback(this); 
     ...# window实例
     #Activity 参数配置
     
     mWindow.setWindowManager(
         (WindowManager)context.getSystemService(Context.WINDOW_SERVICE),
         mToken, mComponent.flattenToString(),
         (info.flagActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0);
    # window 设置WindowManager
 }

通常我们在onCreate里做的一个比较重要动作就是setContentView(int id)通过源码会发现最终调用的是Phonewindow的setContentView()现在我们分析下这个方法做了哪些工作

DecorView的创建


public void setContentView(int layoutResID) {
    if (mContentParent == null) {
        installDecor();#1 初始化DecorView
    } else if (!hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
        mContentParent.removeAllViews();
    }

    if (hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
        final Scene newScene = Scene.getSceneForLayout(mContentParent, layoutResID,
                getContext());
        transitionTo(newScene);
    } else {
        mLayoutInflater.inflate(layoutResID, mContentParent);
        #2解析布局文件通过反射实例化相对应的view
    }
    mContentParent.requestApplyInsets();
    final Callback cb = getCallback();
    if (cb != null && !isDestroyed()) {
        cb.onContentChanged();
    }
    mContentParentExplicitlySet = true;
}

注释1

private void installDecor() {
    if (mDecor == null) {
        mDecor = generateDecor(-1);#实例化
        mDecor.setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS);
        mDecor.setIsRootNamespace(true);
        if (!mInvalidatePanelMenuPosted && mInvalidatePanelMenuFeatures != 0) {
            mDecor.postOnAnimation(mInvalidatePanelMenuRunnable);
        }
    } else {
        mDecor.setWindow(this);
    }
   if (mContentParent == null) {
        mContentParent = generateLayout(mDecor);
        #除导航栏状态栏,内容都显示在这
   }    
}

ViewRootImpl创建

handleStartActivity()这个方法对我们分析比较不重要跳过 handleResumeActivity() 我们知道这个方法过后内容才会显示出来,分析下都做了哪些工作

 public void handleResumeActivity(IBinder token, boolean finalStateRequest, boolean isForward, String reason) {
     // TODO Push resumeArgs into the activity for consideration
    final ActivityClientRecord r = performResumeActivity(tokenfinalStateRequest, reason);
    #调用 Activity的onResume()
    if (r.window == null && !a.mFinished && willBeVisible) {
        r.window = r.activity.getWindow();
        View decor = r.window.getDecorView();
        decor.setVisibility(View.INVISIBLE);
        ViewManager wm = a.getWindowManager();
        WindowManager.LayoutParams l = r.window.getAttributes();
        a.mDecor = decor;
        ....
        if (a.mVisibleFromClient) {
                if (!a.mWindowAdded) {
                    a.mWindowAdded = true;
                    wm.addView(decor, l);
                    #1 
                } else {
                    // The activity will get a callback for this {@link LayoutParams} change
                    // earlier. However, at that time the decor will not be set (this is set
                    // in this method), so no action will be taken. This call ensures the
                    // callback occurs with the decor set.
                    a.onWindowAttributesChanged(l);
                }
            }
    }
 }

跟踪 addView()-> mGlobal.addView()

WindowManagerGlobal
public void addView(View view, ViewGroup.LayoutParams params, Display display, Window parentWindow) {
    ...
    root = new ViewRootImpl(view.getContext(), display);
    # ViewRootImpl创建
    mViews.add(view);
    mRoots.add(root);
    mParams.add(wparams);
    try {
        root.setView(view, wparams, panelParentView);
    } catch (RuntimeException e) {
        // BadTokenException or InvalidDisplayException, clean up.
        if (index >= 0) {
          removeViewLocked(index, true);
        }
        throw e;
    }
}

ViewRootImpl 的 setView()

ViewRootImpl
 public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {
    ...
      requestLayout();//此处会先进行一次测量
      res = mWindowSession.addToDisplay(mWindow, mSeq, mWindowAttributes,getHostVisibility(), mDisplay.getDisplayId(),
      mWinFrame,mAttachInfo.mContentInsets, mAttachInfo.mStableInsets,mAttachInfo.mOutsets, mAttachInfo.mDisplayCutout, mInputChannel);
      #1 mWindow 接收来自WMS的相关指令
      #与WMS建立Session通信
      mInputEventReceiver = new WindowInputEventReceiver(mInputChannel,
                            Looper.myLooper());
     #创建接收事件的Receiver 后续的点击事件都由此收到并进行分发
 }

ViewRootImpl::W{
    ...

    public void windowFocusChanged(boolean hasFocus, boolean inTouchMode) 
    # 进行页面的显示
    ...
}

requestLayout()->scheduleTraversals() 看到这个scheduleTraversals()是不是一切都明朗起来了

趁热打铁继续分析scheduleTraversals()做的工作

 void scheduleTraversals() {
        if (!mTraversalScheduled) {
            mTraversalScheduled = true;
            mTraversalBarrier = mHandler.getLooper().getQueue().postSyncBarrier();
            #往loope里发送屏障信息,looper会遍历整个列表直到有相应关于异步的信息(屏障信息没有target,loop循环时发现没有target的信息,会继续搜索队列中的异步信息,直到查找到优先处理)
            mChoreographer.postCallback(
                    Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);
            #发送更新视图的异步信息,该信息会优先被处理
            #1、通过handler发送traversal信息
            #2、Choreographer.scheduleFrameLocked()->scheduleVsyncLocked();-> mDisplayEventReceiver.scheduleVsync();注册时间片段
            #3、FrameDisplayEventReceiver.onVsync()收到刷新信息, scheduleVsync();继续注册
            #4、发送刷新信息-> doFrame(mTimestampNanos, mFrame);
            #5、doCallbacks(Choreographer.CALLBACK_TRAVERSAL,frameTimeNanos);->c.run()->doTraversal()
            
            if (!mUnbufferedInputDispatch) {
                scheduleConsumeBatchedInput();
            }
            notifyRendererOfFramePending();
            pokeDrawLockIfNeeded();
        }
    }