前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Android框架简介--Activity--Activity启动

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

作者头像
小蚂蚁与大象
发布2022-04-02 08:04:25
6650
发布2022-04-02 08:04:25
举报

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

startActivity.png

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

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

代码语言:javascript
复制
startActivity(new Intent(A_Activity.this,B_Activity.class));

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

代码语言:javascript
复制
    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组件单元测试。这里不做深究。

代码语言:javascript
复制
 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

代码语言:javascript
复制
/**
 * 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

代码语言:javascript
复制
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流程

代码语言:javascript
复制
    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

代码语言:javascript
复制
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

代码语言:javascript
复制
    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

代码语言:javascript
复制
 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

代码语言:javascript
复制
    public static void main(String[] args) {
        Looper.prepareMainLooper();

        ActivityThread thread = new ActivityThread();
        thread.attach(false);

        Looper.loop();
    }
代码语言:javascript
复制
 private void attach(boolean system) {
           final IActivityManager mgr = ActivityManager.getService();
            try {
                mgr.attachApplication(mAppThread);
            } catch (RemoteException ex) {
                throw ex.rethrowFromSystemServer();
            }
}

这里的attach就是向AMS注册

下面回到AMS中去执行

代码语言:javascript
复制
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)
         
}
代码语言:javascript
复制
boolean attachApplicationLocked(ProcessRecord app)  {
      final ActivityRecord top = stack.topRunningActivityLocked();
      realStartActivityLocked(activity, app,
}

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

代码语言:javascript
复制
final boolean realStartActivityLocked() {
    app.thread.scheduleLaunchActivity
}

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

第五步 Activity启动

下面就切回到ActivityThread中去执行

代码语言:javascript
复制
public final void scheduleLaunchActivity() {
    ActivityClientRecord r = new ActivityClientRecord();
    sendMessage(H.LAUNCH_ACTIVITY, r);
}

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

代码语言:javascript
复制
 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的生命周期

代码语言:javascript
复制
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);
            }
}
代码语言:javascript
复制
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高级职位

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2022.03.27 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 第一步 Activity A 调用AMS 启动接口
  • 第二步 收集应用信息,pause ActivityA
  • 第三步 通过Zygote创建应用进程
  • 第四步 应用进程启动及跟AMS交互
  • 第五步 Activity启动
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档