Android Activity的启动过程分析

   1 Activity的常见启动方式

      1.1长按Home键,显示最近运行Task列表,选择启动其中一个Task的当前Activity。

      1.2在一个应用中,按Back键,结束当前Activity,返回上一个Activity。

      1.3在Home桌面点击应用程序的图标启动应用程序。其实质是启动应用程序的主Activity。

      1.4在应用程序中调用startActivity(intent)启动另一个Activity。

      1.5通过adb shell 命令登录手机,执行am start命令启动指定的Activity。

   2 过程分析

      选最常见的启动方式startActivity(intent)来分析。

Intent intent=new Intent(MainActivity.this,TestActivity.class);startActivity(intent);

 #Activity

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

分析:经过startActivity-->startActivityForResult-->execStartActivity,最终会调用Instrumentation的execStartActivity方法。

# Instrumentation

public ActivityResult execStartActivity(           Context who, IBinder contextThread, IBinder token, Activity target,           Intent intent, int requestCode, Bundle options) {...  //获取AMS的代理,启动Activity  发起请求           int result = ActivityManagerNative.getDefault()               .startActivity(whoThread, who.getBasePackageName(), intent,                       intent.resolveTypeIfNeeded(who.getContentResolver()),                       token, target != null ? target.mEmbeddedID : null,                       requestCode, 0, null, options);...}

# ActivityManagerService 

  处理Activity的启动请求

 @Override    public final int startActivity(IApplicationThread caller, String callingPackage,            Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,            int startFlags, ProfilerInfo profilerInfo, Bundle bOptions) {        return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,                resultWho, requestCode, startFlags, profilerInfo, bOptions,                UserHandle.getCallingUserId());    }
 @Override    public final int startActivityAsUser(IApplicationThread caller, String callingPackage,            Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,            int startFlags, ProfilerInfo profilerInfo, Bundle bOptions, int userId) {        enforceNotIsolatedCaller("startActivity");        userId = mUserController.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),                userId, false, ALLOW_FULL_ONLY, "startActivity", null);        // TODO: Switch to user app stacks here.        return mActivityStarter.startActivityMayWait(caller, -1, callingPackage, intent,                resolvedType, null, null, resultTo, resultWho, requestCode, startFlags,                profilerInfo, null, null, bOptions, false, userId, null, null,                "startActivityAsUser");    }

为了减少篇幅,省略一部分

 # ActivityStarter startActivityMayWait() # ActivityStarter startActivityLocked() # ActivityStarter startActivity() # ActivityStarter startActivityUnchecked()  #ActivityStackSupervisor resumeFocusedStackTopActivityLocked() #ActivityStack resumeTopActivityUncheckedLocked() #ActivityStack resumeTopActivityInnerLocked # ActivityStackSupervisor  startSpecificActivityLocked
# ActivityStackSupervisor  realStartActivityLocked

这一步比较关键,涉及到服务端AMS调用客户端ActivityThread.

final boolean realStartActivityLocked(ActivityRecord r, ProcessRecord app,            boolean andResume, boolean checkConfig) throws RemoteException {...  app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,                    System.identityHashCode(r), r.info,                    // TODO: Have this take the merged configuration instead of separate global and                    // override configs.                    mergedConfiguration.getGlobalConfiguration(),                    mergedConfiguration.getOverrideConfiguration(), r.compat,                    r.launchedFromPackage, task.voiceInteractor, app.repProcState, r.icicle,                    r.persistentState, results, newIntents, !andResume,                    mService.isNextTransitionForward(), profilerInfo);...}

app.thread就是ApplicationThreadProxy在服务端的代理对象。

# ActivityThread(内部类) # ApplicationThread scheduleLaunchActivity()
 @Override        public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,                ActivityInfo info, Configuration curConfig, Configuration overrideConfig,                CompatibilityInfo compatInfo, String referrer, IVoiceInteractor voiceInteractor,                int procState, Bundle state, PersistableBundle persistentState,                List pendingResults, List pendingNewIntents,                boolean notResumed, boolean isForward, ProfilerInfo profilerInfo) {            ...           //给 H handler发送一个消息              sendMessage(H.LAUNCH_ACTIVITY, r);        }
  private class H extends Handler {...public void handleMessage(Message msg) {            if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));            switch (msg.what) {                case LAUNCH_ACTIVITY: {                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStart");                    final ActivityClientRecord r = (ActivityClientRecord) msg.obj;                    r.packageInfo = getPackageInfoNoCheck(                            r.activityInfo.applicationInfo, r.compatInfo);                    handleLaunchActivity(r, null, "LAUNCH_ACTIVITY");                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);                } break;...}

#ActivityThread

private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) {        // If we are getting ready to gc after going to the background, well        // we are back active so skip it.... Activity a = performLaunchActivity(r, customIntent);...}
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {        // System.out.println("##### [" + System.currentTimeMillis() + "] ActivityThread.performLaunchActivity(" + r + ")");...Activity activity = null;        try {            java.lang.ClassLoader cl = r.packageInfo.getClassLoader();            activity = mInstrumentation.newActivity(                    cl, component.getClassName(), r.intent);            StrictMode.incrementExpectedActivityCount(activity.getClass());            r.intent.setExtrasClassLoader(cl);            r.intent.prepareToEnterProcess();            if (r.state != null) {                r.state.setClassLoader(cl);            }        }... try {            Application app = r.packageInfo.makeApplication(false, mInstrumentation);... 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);if (r.isPersistable()) {                    mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);                } else {                    mInstrumentation.callActivityOnCreate(activity, r.state);                }...}

通过Instrumentation来回调Activity的各生命周期方法

#Instrumentation

public void callActivityOnCreate(Activity activity, Bundle icicle) {        prePerformCreate(activity);        activity.performCreate(icicle);        postPerformCreate(activity);    }

#Activity

 final void performCreate(Bundle icicle) {        restoreHasCurrentPermissionRequest(icicle);        onCreate(icicle);        mActivityTransitionState.readState(icicle);        performCreateCommon();    }

至此,一个Activity的启动流程完成。




 

 

 

 

更多相关文章

  1. 编写一个基本的Android​应用程序
  2. ARCVM:Chrome OS 中运行 Android 应用程序的新方式
  3. Mqtt从服务端到Android客户端搭建(Android客户端搭建)
  4. 在任意位置获取应用程序Context
  5. Android 应用程序主框架搭建

随机推荐

  1. android的开发 华为手机上不显示menu键
  2. 活动的启动模式汇总
  3. import android eclipse project to andr
  4. android全屏设置代码:
  5. Android查看源码
  6. Android(安卓)UI设计随笔
  7. android
  8. Android下图片或按钮等可拖动到任意位置
  9. Android给ListView设置分割线Divider样式
  10. SQLiteDatabase 启用事务源码分析