美文网首页
Android框架简介--Activity--Activity启

Android框架简介--Activity--Activity启

作者: llm_5243 | 来源:发表于2022-03-27 11:54 被阅读0次

    以Activity A 启动 Activity B,Activity B所在进程未启动为例
    大体经过已经几个阶段:

    startActivity.png

    第一步 Activity A 调用AMS 启动接口

    这是一个binder通讯,正常启动Activity的方式,一般我们都会通过以下的方式启动一个新的Activity

    startActivity(new Intent(A_Activity.this,B_Activity.class));
    

    这是Activity类的接口,最终会调用到

        public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,
                @Nullable Bundle options) {
            if (mParent == null) {
                options = transferSpringboardActivityOptions(options);
                Instrumentation.ActivityResult ar =
                    mInstrumentation.execStartActivity(
                        this, mMainThread.getApplicationThread(), mToken, this,
                        intent, requestCode, options);
                if (ar != null) {
                    mMainThread.sendActivityResult(
                        mToken, mEmbeddedID, requestCode, ar.getResultCode(),
                        ar.getResultData());
                }
    
                cancelInputsAndStartExitTransition(options);
                // TODO Consider clearing/flushing other event sources and events for child windows.
            } else {
              
            }
        }
    
    

    这里关键点会调用Instrumentation 的execStartActivity方法。
    frameworks/base/core/java/android/app/Instrumentation.java
    源码注释大体意思是Instrumentation类会在应用的任何代码执行前被实列化,用来监控系统与应用的交互。可在以应用的AndroidManifest.xml中<instrumentation>标签来注册一个Instrumentation的实现。
    基本上在application和activity的所有生命周期调用中,都会先调用instrumentation的相应方法。Instrumentation另一个重要作用是提供Android组件单元测试。这里不做深究。

     public ActivityResult execStartActivity(
                Context who, IBinder contextThread, IBinder token, Activity target,
                Intent intent, int requestCode, Bundle options) {
           ...
            try {
                intent.migrateExtraStreamToClipData();
                intent.prepareToLeaveProcess(who);
                //核心在这一句
                int result = ActivityManager.getService()
                    .startActivity(whoThread, who.getBasePackageName(), intent,
                            intent.resolveTypeIfNeeded(who.getContentResolver()),
                            token, target != null ? target.mEmbeddedID : null,
                            requestCode, 0, null, options);
                checkStartActivityResult(result, intent);
            } catch (RemoteException e) {
                throw new RuntimeException("Failure from system", e);
            }
            return null;
        }
    
    

    ActivityManager.getService().startActivity 这一步会通过binder的方式调用到AMS的接口

    第二步 收集应用信息,pause ActivityA

    startActivity --> startActivityAsUser -- > mActivityStarter.startActivityMayWait

    这里会调用到类 ActivityStarter

    /**
     * Controller for interpreting how and then launching activities.
     *
     * This class collects all the logic for determining how an intent and flags should be turned into
     * an activity and associated task and stack.
     */
    class ActivityStarter
    

    从注释上看,我们了解了ActivityStarter的作用是收集所有的逻辑,用来决定如何启动activity, ActivityStarter又通过ActivityStackSupervisor来管理ActivityStack

    略过中间环节,会调用到ActivityStack的resumeTopActivityInnerLocked

    boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {
        // ......
        boolean pausing = getDisplay().pauseBackStacks(userLeaving, next, false);
        if (mResumedActivity != null) {
            if (DEBUG_STATES) Slog.d(TAG_STATES,
                    "resumeTopActivityLocked: Pausing " + mResumedActivity);
            pausing |= startPausingLocked(userLeaving, false, next, false);
        }
        // ......
        if (next.attachedToProcess()) {
            try {
            // ......
                transaction.setLifecycleStateRequest(
                        ResumeActivityItem.obtain(next.app.getReportedProcState(),
                                getDisplay().mDisplayContent.isNextTransitionForward()));
                mService.getLifecycleManager().scheduleTransaction(transaction);
            } catch (Exception e) {
                // ......
                mStackSupervisor.startSpecificActivityLocked(next, true, false);
                return true;
            }
            // ......
        } else {
            // Whoops, need to restart this activity!
            if (!next.hasBeenLaunched) {
                next.hasBeenLaunched = true;
            } else {
                if (SHOW_APP_STARTING_PREVIEW) {
                    next.showStartingWindow(null /* prev */, false /* newTask */,
                            false /* taskSwich */);
                }
                if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Restarting: " + next);
            }
            if (DEBUG_STATES) Slog.d(TAG_STATES, "resumeTopActivityLocked: Restarting " + next);
            mStackSupervisor.startSpecificActivityLocked(next, true, true);
        }
    
        return true;
    }
    

    此处先通过startPausingLocked流程使mResumedActivity pause。

    第三步 通过Zygote创建应用进程

    下一步则通过 ActivityStackSupervisor 中的startSpecificActivityLocked方法来执行启动ActivityB流程

        void startSpecificActivityLocked(ActivityRecord r,
                boolean andResume, boolean checkConfig) {
            // Is this activity's application already running?
            ProcessRecord app = mService.getProcessRecordLocked(r.processName,
                    r.info.applicationInfo.uid, true);
    
    
            if (app != null && app.thread != null) {
                try {
                    realStartActivityLocked(r, app, andResume, checkConfig);
                    return;
                } 
    
                // If a dead object exception was thrown -- fall through to
                // restart the application.
            }
    
            mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
                    "activity", r.intent.getComponent(), false, false, true);
        }
    

    这个函数,先判断ActivityB所在的进程是否启动,如果已经启动则执行realStartActivityLocked, 如果没有则走mService.startProcessLocked流程去启动一个进程. mService为ActivityManagerService

    private final void startProcessLocked(ProcessRecord app,) {
    
           if (entryPoint == null) entryPoint = "android.app.ActivityThread";
           startResult = Process.start(entryPoint,);
    
           synchronized (mPidsSelfLocked) {
                    this.mPidsSelfLocked.put(startResult.pid, app);
                    if (isActivityProcess) {
                        Message msg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
                        msg.obj = app;
                        mHandler.sendMessageDelayed(msg, startResult.usingWrapper
                                ? PROC_START_TIMEOUT_WITH_WRAPPER : PROC_START_TIMEOUT);
                    }
                }
    }
    

    frameworks/base/core/java/android/os/Process.java

        public static final ProcessStartResult start(final String processClass,) {
            return zygoteProcess.start(processClass, niceName, uid, gid, gids,
                        debugFlags, mountExternal, targetSdkVersion, seInfo,
                        abi, instructionSet, appDataDir, invokeWith, zygoteArgs);
        }
    

    frameworks/base/core/java/android/os/Process.java

     public final Process.ProcessStartResult start(final String processClass,) {
            try {
                return startViaZygote(processClass, );
            } 
        }
    

    这里 entryPoint = "android.app.ActivityThread" 为启动的java类, 该变量会作为参数给到Process。 Process.start(entryPoint,) 最终会通过socket跟Zygote通讯,Zygote 会去fork一个进程,入口就是entryPoint。

    Zygote启动完进程后会返回一个pid,这个pid包含在startResult里面,接着会将pid和app 放入mPidsSelfLocked, 并发送一个延时消息,如果ActivityThread在一定的TIMEOUT(10s)还没向AMS报告,则该消息会被执行,AMS会去清除这个应用的所有信息

    第四步 应用进程启动及跟AMS交互

    frameworks/base/core/java/android/app/ActivityThread.java

        public static void main(String[] args) {
            Looper.prepareMainLooper();
    
            ActivityThread thread = new ActivityThread();
            thread.attach(false);
    
            Looper.loop();
        }
    
     private void attach(boolean system) {
               final IActivityManager mgr = ActivityManager.getService();
                try {
                    mgr.attachApplication(mAppThread);
                } catch (RemoteException ex) {
                    throw ex.rethrowFromSystemServer();
                }
    }
    

    这里的attach就是向AMS注册

    下面回到AMS中去执行

    private final boolean attachApplicationLocked(IApplicationThread thread, int pid) {
            //首先根据pid取出 ProcessRecord
            app = mPidsSelfLocked.get(pid);
    
            //thread为应用端的binder对象,会去通知应用端做一些Application初始化
             thread.bindApplication(processName,...)
             ...
             //处理被挂起的应用组件(activity,service,broadcast),之前应用进程还没被创建
             mStackSupervisor.attachApplicationLocked(app)
             ...
             mServices.attachApplicationLocked()
    
             sendPendingBroadcastsLocked(app)
             
    }
    
    boolean attachApplicationLocked(ProcessRecord app)  {
          final ActivityRecord top = stack.topRunningActivityLocked();
          realStartActivityLocked(activity, app,
    }
    

    stack为mFocusStack, 这一部为取出栈顶的Activity,即我们要启动的activity,虽然之前activity没启动,但ams里面栈的信息在启动进程前都已经准备好了。

    final boolean realStartActivityLocked() {
        app.thread.scheduleLaunchActivity
    }
    

    app为ProcessRecord对象,thread为应用注册到AMS的binder对象. 这里调用了应用的scheduleLaunchActivity,从名字看表示可以加载activity了

    第五步 Activity启动

    下面就切回到ActivityThread中去执行

    public final void scheduleLaunchActivity() {
        ActivityClientRecord r = new ActivityClientRecord();
        sendMessage(H.LAUNCH_ACTIVITY, r);
    }
    

    通过发送消息给主线程去处理

     public void handleMessage(Message msg) {
                switch (msg.what) {
                    case LAUNCH_ACTIVITY: {
    
                        final ActivityClientRecord r = (ActivityClientRecord) msg.obj;
    
                        r.packageInfo = getPackageInfoNoCheck(
                                r.activityInfo.applicationInfo, r.compatInfo);
                        handleLaunchActivity(r, null, "LAUNCH_ACTIVITY");
                    } break;
    

    getPackageInfoNoCheck 会去loadApk加载apk的一些信息,后面启动activity需要调用到,下面会去执行的activity的生命周期

    private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) {
        Activity a = performLaunchActivity(r, customIntent);
        if (a != null) {
                handleResumeActivity(r.token, false, r.isForward,
                        !r.activity.mFinished && !r.startsNotResumed, r.lastProcessedSeq, reason);
                }
    }
    
    private Activity performLaunchActivity {
          //创建一个Activity
          activity = mInstrumentation.newActivity(
                        cl, component.getClassName(), r.intent);
           // 获取之前创建的Application
           Application app = r.packageInfo.makeApplication(false, mInstrumentation);
            //创建Context, 并将Context赋值给activity
            ContextImpl appContext = createBaseContextForActivity(r);
           activity.attach(appContext, this, ...)
    
           //调用到Activity onCreate函数 
           mInstrumentation.callActivityOnCreate(activity, r.state);
           //调用到Activity onStart函数 
           activity.performStart();
    }
    

    大体流程可以用下图表示

    activity启动.png

    参考:
    网络课程 --剖析Framework面试 冲击Android高级职位

    相关文章

      网友评论

          本文标题:Android框架简介--Activity--Activity启

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