我是靠谱客的博主 缓慢酒窝,最近开发中收集的这篇文章主要介绍关于 Activity 启动流程的知识点汇总,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

Activity启动的流程分为两部分:

  • 一是在activity中通过startActivity(Intent intent)方法启动一个Activity;

  • 二是我们在桌面通过点击应用图标启动一个App然后显示Activity;

第二种方式相较于第一种方式更加全面,所以本文会以第二种流程来分析。

简要

我们手机的桌面是一个叫做Launcher的Activity,它罗列了手机中的应用图标,图标中包含安装apk时解析的应用默认启动页等信息。在点击应用图标时,即将要启动的App和Launcher、AMS、Zygote所属进程不同所以涉及到Launcher与AMS,AMS与Zygote,AMS与新App这四者多次通信,才会启动一个App,然后再启动Activity,整体的时序图如下:

图片

image

接下来根据源码来梳理一下流程。

1.Launcher向AMS发送启动Activity

Launcher本身是一个Activity,在用户点击应用图标时,调用startActivitySafely方法,最后调用到Activity.startActivity(),函数调用如下

Launcher.java
   public boolean startActivitySafely(View v, Intent intent, ItemInfo item) {
       ...
       //标记在新的栈启动
       intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
       ...
       startActivity(intent, optsBundle);
       ...
   }

Activity.java
   @Override
   public void startActivity(Intent intent) {
       this.startActivity(intent, null);
   }

   @Override
   public void startActivity(Intent intent, @Nullable Bundle options) {
       ...
       if (options != null) {
           //-1为requestCode表明不需要知道是否启动成功
           startActivityForResult(intent, -1, options);
       } else {
           startActivityForResult(intent, -1);
       }
   }

   public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,
           @Nullable Bundle options) {
           ...
           Instrumentation.ActivityResult ar =
               mInstrumentation.execStartActivity(
                   this, mMainThread.getApplicationThread(), mToken,this,intent, requestCode, options);
           ...
    }

每个Activity都持有Instrumentation对象,通过它的execStartActivity函数来继续完成启动Activity的流程,这个函数中传入了mMainThread.getApplicationThread(),它获取到的是ActivityThread的内部类ApplicationThread,这是一个Binder对象,之后AMS通过此对象与App的通信。

Instrumentation.java
public ActivityResult execStartActivity(
            Context who, IBinder contextThread, IBinder token, Activity target,
            Intent intent, int requestCode, Bundle options) {
    ...
    int result = ActivityTaskManager.getService().startActivity(whoThread,who.getBasePackageName(),
        who.getAttributionTag(),intent,intent.resolveTypeIfNeeded(who.getContentResolver()),
        token,target != null ? target.mEmbeddedID : null, requestCode, 0, null, options); 
    ...
}

ActivityTaskManager.java
public static IActivityTaskManager getService() {
       return IActivityTaskManagerSingleton.get();
}

private static final Singleton<IActivityTaskManager> IActivityTaskManagerSingleton =
            new Singleton<IActivityTaskManager>() {
                @Override
                protected IActivityTaskManager create() {
                    final IBinder b = ServiceManager.getService(Context.ACTIVITY_TASK_SERVICE);
                    return IActivityTaskManager.Stub.asInterface(b);
                }
             }
};

这一步Launcher开始向AMS通信,由于在不同的进程所以需要通过Binder来通信,IActivityTaskManager是一个代理AMS端Binder的对象,之后AMS开始startActivity。 到这里Launcher向AMS请求启动一个Activity的流程就结束了。

2.AMS启动Activity并通知Launcher进入Paused

现在的流程是在AMS中,也就是另一个进程中,上一步通过代理调用到AMS的startActivity方法,接下来的调用如下:

ActivityTaskManagerService.java
    @Override
    public final int startActivity(IApplicationThread caller, String callingPackage,
            String callingFeatureId, Intent intent, String resolvedType, IBinder resultTo,
            String resultWho, int requestCode, int startFlags, ProfilerInfo profilerInfo,
            Bundle bOptions) {
        return startActivityAsUser(caller, callingPackage, callingFeatureId, intent, resolvedType,
                resultTo, resultWho, requestCode, startFlags, profilerInfo, bOptions,
                UserHandle.getCallingUserId());
    }

    @Override
    public int startActivityAsUser(IApplicationThread caller, String callingPackage,
            String callingFeatureId, Intent intent, String resolvedType, IBinder resultTo,
            String resultWho, int requestCode, int startFlags, ProfilerInfo profilerInfo,
            Bundle bOptions, int userId) {
        return startActivityAsUser(caller, callingPackage, callingFeatureId, intent, resolvedType,
                resultTo, resultWho, requestCode, startFlags, profilerInfo, bOptions, userId,
                true /*validateIncomingUser*/);
    }

    private int startActivityAsUser(IApplicationThread caller, String callingPackage,
            @Nullable String callingFeatureId, Intent intent, String resolvedType,
            IBinder resultTo, String resultWho, int requestCode, int startFlags,
            ProfilerInfo profilerInfo, Bundle bOptions, int userId, boolean validateIncomingUser) {
        ...
        userId = getActivityStartController().checkTargetUser(userId, validateIncomingUser,
                Binder.getCallingPid(), Binder.getCallingUid(), "startActivityAsUser");

        return getActivityStartController().obtainStarter(intent, "startActivityAsUser")
                .setCaller(caller)
                .setCallingPackage(callingPackage)
                .setCallingFeatureId(callingFeatureId)
                .setResolvedType(resolvedType)
                .setResultTo(resultTo)
                .setResultWho(resultWho)
                .setRequestCode(requestCode)
                .setStartFlags(startFlags)
                .setProfilerInfo(profilerInfo)
                .setActivityOptions(bOptions)
                .setUserId(userId)
                .execute();
    }

    ActivityStarter obtainStarter(Intent intent, String reason) {
        return mFactory.obtain().setIntent(intent).setReason(reason);
    }

上面几步主要是做权限检查

ActivityStarter.java
 int execute() {
 ...
 res = executeRequest(mRequest);
 ...
 }
//层层调用会到下面这个方法
ActivityStack.java
 private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {
    ...
    if (mResumedActivity != null) {
       pausing |= startPausingLocked(userLeaving, false , next);
    }
    ...
    mStackSupervisor.startSpecificActivity(next, true, false);
    ...
 }

startPausingLocked方法主要是通知Launcher进入Paused状态,在它进入这个状态后,在ActivityStackSupervisor.startSpecificActivity方法判断新的App进程状态做出不同响应,如下:

ActivityStackSupervisor.java
void startSpecificActivity(ActivityRecord r, boolean andResume, boolean checkConfig) {
        // 获取要启动的Activity进程信息
        final WindowProcessController wpc =
                mService.getProcessController(r.processName, r.info.applicationInfo.uid);
        boolean knownToBeDead = false;
        //如果进程存在且有进程中有线程存在 就是启动一个同应用的Activity(普通Activity就在此执行)
        if (wpc != null && wpc.hasThread()) {
            try {
                realStartActivityLocked(r, wpc, andResume, checkConfig);
                return;
            } catch (RemoteException e) {
                Slog.w(TAG, "Exception when starting activity "
                        + r.intent.getComponent().flattenToShortString(), e);
            }

            // If a dead object exception was thrown -- fall through to
            // restart the application.
            knownToBeDead = true;
        }
    //否则通过AMS向Zygote进程请求创建新的进程
        r.notifyUnknownVisibilityLaunchedForKeyguardTransition();
        final boolean isTop = andResume && r.isTopRunningActivity();
        mService.startProcessAsync(r, knownToBeDead, isTop, isTop ? "top-activity" : "activity");
}

截止到这里完成了Launcher和AMS的通信,以及AMS和Zygote进程的通信,接下来我们要创建要启动的App的线程,即ActivityThread。

3.新的进程启动,ActivityThread的main函数

上一部分Zygote启动新的进程时标记ActivityThread.main函数,在Zygote创建好新进程后通过反射调用此方法,现在处于新App的进程中。

ActivityThread.java
    public static void main(String[] args) {
        ...
        Looper.prepareMainLooper();
    ...
        ActivityThread thread = new ActivityThread();
        thread.attach(false, startSeq);
    ...
        Looper.loop();
    ...
    }

    private void attach(boolean system, long startSeq) {
            final IActivityManager mgr = ActivityManager.getService();
            try {
                mgr.attachApplication(mAppThread, startSeq);
            } catch (RemoteException ex) {
                throw ex.rethrowFromSystemServer();
            }
            ...
    }
ActivityManagerService.java
    private boolean attachApplicationLocked(@NonNull IApplicationThread thread,
            int pid, int callingUid, long startSeq) {
            ...
            thread.bindApplication(processName, appInfo, providerList,
                        instr2.mClass,
                        profilerInfo, instr2.mArguments,
                        instr2.mWatcher,
                        instr2.mUiAutomationConnection, testMode,
                        mBinderTransactionTrackingEnabled, enableTrackAllocation,
                        isRestrictedBackupMode || !normalMode, app.isPersistent(),
                        new Configuration(app.getWindowProcessController().getConfiguration()),
                        app.compat, getCommonServicesLocked(app.isolated),
                        mCoreSettingsObserver.getCoreSettingsLocked(),
                        buildSerial, autofillOptions, contentCaptureOptions,
                        app.mDisabledCompatChanges);
             ...
             didSomething = mAtmInternal.attachApplication(app.getWindowProcessController());
             ...
    }

这里主要是创建了Looper和ActivityThread对象,然后将当前应用ApplicationThread注册到AMS中,ApplicationThread是ActivityThread的内部类实现了IApplicationThread.Stub用此对象可跨进程通信。

最后

以上就是缓慢酒窝为你收集整理的关于 Activity 启动流程的知识点汇总的全部内容,希望文章能够帮你解决关于 Activity 启动流程的知识点汇总所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(55)

评论列表共有 0 条评论

立即
投稿
返回
顶部