Quantcast
Channel: CSDN博客移动开发推荐文章
Viewing all articles
Browse latest Browse all 5930

Android源码解析四大组件系列(四)---Activity启动详细流程

$
0
0

在上一篇博客http://www.jianshu.com/p/98fa08ee1bfb,我们起码知道了Zygote是怎么启动SystemServer进程的,AMS是怎么注册的,启动的,启动之后通过Socket怎样与Zygote进程通信的,而Zygote进程收到AMS的请求之后,是怎么fork进程,将ActivityThread的main方法是执行起来的。这些内容在我的前两篇博客都梳理过,建议阅读一下,在看本文。

一、Activity请求启动

启动Activity的方式

我们以startActivity这种来分析

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

经过startActivity–>startActivityForResult–>execStartActivity,最终会调用Instrumentation的execStartActivity方法。

 public ActivityResult execStartActivity(
            Context who, IBinder contextThread, IBinder token, Activity target,
            Intent intent, int requestCode, Bundle options) {
        IApplicationThread whoThread = (IApplicationThread) contextThread;
        Uri referrer = target != null ? target.onProvideReferrer() : null;
        if (referrer != null) {
            intent.putExtra(Intent.EXTRA_REFERRER, referrer);
        }
       .....

        try {
            intent.migrateExtraStreamToClipData();
            intent.prepareToLeaveProcess(who);
            //获取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);

            //检查Activity是否启动成功,若失败给出是什么原因
            checkStartActivityResult(result, intent);
        } catch (RemoteException e) {
            throw new RuntimeException("Failure from system", e);
        }
        return null;

    }

这些参数的意思是

  • this,为启动Activity的对象;
  • contextThread,为Binder对象,是主进程的context对象;
  • token,也是一个Binder对象,指向了服务端一个ActivityRecord对象;
  • target,为启动的Activity;
  • intent,启动的Intent对象;
  • requestCode,请求码;
  • options,参数;

先看checkStartActivityResult方法的实现

 public static void checkStartActivityResult(int res, Object intent) {
        if (res >= ActivityManager.START_SUCCESS) {
            return;
        }

        switch (res) {
            case ActivityManager.START_INTENT_NOT_RESOLVED:
            case ActivityManager.START_CLASS_NOT_FOUND:
                if (intent instanceof Intent && ((Intent)intent).getComponent() != null)
                    throw new ActivityNotFoundException(
                            "Unable to find explicit activity class "
                            + ((Intent)intent).getComponent().toShortString()
                            + "; have you declared this activity in your AndroidManifest.xml?");
                throw new ActivityNotFoundException(
                        "No Activity found to handle " + intent);
            case ActivityManager.START_PERMISSION_DENIED:
                throw new SecurityException("Not allowed to start activity "
                        + intent);
            case ActivityManager.START_FORWARD_AND_REQUEST_CONFLICT:
                throw new AndroidRuntimeException(
                        "FORWARD_RESULT_FLAG used while also requesting a result");
            case ActivityManager.START_NOT_ACTIVITY:
                throw new IllegalArgumentException(
                        "PendingIntent is not an activity");
            case ActivityManager.START_NOT_VOICE_COMPATIBLE:
                throw new SecurityException(
                        "Starting under voice control not allowed for: " + intent);
            case ActivityManager.START_VOICE_NOT_ACTIVE_SESSION:
                throw new IllegalStateException(
                        "Session calling startVoiceActivity does not match active session");
            case ActivityManager.START_VOICE_HIDDEN_SESSION:
                throw new IllegalStateException(
                        "Cannot start voice activity on a hidden session");
            case ActivityManager.START_CANCELED:
                throw new AndroidRuntimeException("Activity could not be started for "
                        + intent);
            default:
                throw new AndroidRuntimeException("Unknown error code "
                        + res + " when starting " + intent);
        }
    }

常见的ActivityNotFoundException,SecurityException等错日志就在这里报出来的。

OK,现在回到execStartActivity,内部调用了ActivityManagerNative.getDefault().startActivity,关于ActivityManagerNative已经说了很多了,相当于AMS服务端存根或者代理,其客户端是ActivityManagerNative的内部类ActivityManagerProxy,这里getDefault获取的就是ActivityManagerProxy对象,通过ActivityManagerProxy对象来使用AMS内部的一些服务,包括单不限于启动Activity。所以通过ActivityManagerProxy对象调用startActivity方法的实质是调用BinderProxy.transact向Binder驱动发送START_ACTIVITY_TRACSACTION命令,binder驱动将处理逻辑从Launcher所在的进程切换到AMS所在的SystemServer进程。OK,我们直接看ActivityManagerService的startActivity方法,不明白,建议看一下Binder的通信原理。

二、AMS处理Activity的启动请求

2.1、AMS处理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());
    }

保持篇幅,以下步骤省略。
ActvityiManagerService.startActivityAsUser()
ActivityStackSupervisor.startActivityMayWait()
ActivityStackSupervisor.startActivityLocked()
ActivityStackSupervisor.startActivityUncheckedLocked()
ActivityStackSupervisor.startActivityLocked()
ActivityStackSupervisor.resumeTopActivitiesLocked()
ActivityStackSupervisor.resumeTopActivityInnerLocked()

在resumeTopActivityInnerLocked的内部有如下代码。

 if (mResumedActivity != null) {
         if (DEBUG_STATES) Slog.d(TAG_STATES,
                    "resumeTopActivityLocked: Pausing " + mResumedActivity);
         pausing |= startPausingLocked(userLeaving, false, true, dontWaitForPause);
 }

这表明在启动一个Activity的时候,前面一个Activity要执行onPause方法,onPause方法是怎么调用的呢?

2.2、AMS调用栈顶Activity的onPause
 final boolean startPausingLocked(boolean userLeaving, boolean uiSleeping, boolean resuming,
            boolean dontWait) {
        ......
        if (mService.mHasRecents && (next == null || next.noDisplay || next.task != prev.task || uiSleeping)) {
            prev.updateThumbnailLocked(screenshotActivities(prev), null);
        }
        stopFullyDrawnTraceIfNeeded();

        mService.updateCpuStats();

        if (prev.app != null && prev.app.thread != null) {
            if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Enqueueing pending pause: " + prev);
            try {
               //调用ApplicationThread的schedulePauseActivity
                prev.app.thread.schedulePauseActivity(prev.appToken, prev.finishing,
                        userLeaving, prev.configChangeFlags, dontWait);
            } catch (Exception e) {
             ......
            }
        }

       ......
    }

这里先留一个问题, 我知道prev.app.thread是ApplicationThreadProxy对象,实际是调用了ApplicationThread的schedulePauseActivity方法,但是AMS是怎么获取到prev.app.thread的呢?

    public final void schedulePauseActivity(IBinder token, boolean finished,
                boolean userLeaving, int configChanges, boolean dontReport) {
            sendMessage(
                    finished ? H.PAUSE_ACTIVITY_FINISHING : H.PAUSE_ACTIVITY,
                    token,
                    (userLeaving ? 1 : 0) | (dontReport ? 2 : 0),
                    configChanges);
        }

关键就是最后调用了sendMessage(H.BIND_APPLICATION, data),发送了消息。关于H这个类,其实是个Hander,我觉得它的作用就像是一个交通枢纽。对这个H想更详细了解的,详细戳我。H接收到这个Message之后,调用

  handlePauseActivity((IBinder)msg.obj, false, (msg.arg1&1) != 0, msg.arg2,   (msg.arg1&2) != 0);
    private void handlePauseActivity(IBinder token, boolean finished,
            boolean userLeaving, int configChanges, boolean dontReport) {
        ActivityClientRecord r = mActivities.get(token);
            .......
            r.activity.mConfigChangeFlags |= configChanges;
            performPauseActivity(token, finished, r.isPreHoneycomb());
            .......

            // Tell the activity manager we have paused.
            if (!dontReport) {
                try {
                    ActivityManagerNative.getDefault().activityPaused(token);
                } catch (RemoteException ex) {
                }
            }
            mSomeActivitiesChanged = true;
        }
    }
    final Bundle performPauseActivity(ActivityClientRecord r, boolean finished,
            boolean saveState) {
        if (r.paused) {
         .......
        try {
          .......
            //调用Instrumentation的callActivityOnPause方法
            mInstrumentation.callActivityOnPause(r.activity);
            EventLog.writeEvent(LOG_AM_ON_PAUSE_CALLED, UserHandle.myUserId(),
                    r.activity.getComponentName().getClassName());
            if (!r.activity.mCalled) {
                throw new SuperNotCalledException(
                    "Activity " + r.intent.getComponent().toShortString() +
                    " did not call through to super.onPause()");
            }

        } catch (SuperNotCalledException e) {
            throw e;

        } catch (Exception e) {
            .......
            }
        }
        r.paused = true;

         .......
        return !r.activity.mFinished && saveState ? r.state : null;
    }
  public void callActivityOnPause(Activity activity) {
        activity.performPause();
    }
   final void performPause() {
        mDoReportFullyDrawn = false;
        mFragments.dispatchPause();
        mCalled = false;
        //onPause执行
        onPause();
        mResumed = false;
        if (!mCalled && getApplicationInfo().targetSdkVersion
                >= android.os.Build.VERSION_CODES.GINGERBREAD) {
            throw new SuperNotCalledException(
                    "Activity " + mComponent.toShortString() +
                    " did not call through to super.onPause()");
        }
        mResumed = false;
    }

分析到这里 onPause()终于执行了。回到 handlePauseActivity方法中,在这个方法最后调用了ActivityManagerNative.getDefault().activityPaused(token)

2.3、ActivityManagerService的activityPaused方法执行。
  @Override
    public final void activityPaused(IBinder token) {
        final long origId = Binder.clearCallingIdentity();
        synchronized(this) {
            ActivityStack stack = ActivityRecord.getStackLocked(token);
            if (stack != null) {
                stack.activityPausedLocked(token, false);
            }
        }
        Binder.restoreCallingIdentity(origId);
    }

经过一些方法,最终会调用startSpecificActivityLocked
ActivityStack.activityPausedLocked()
ActivityStack.completePauseLocked()
ActivityStackSupervisor.resumeTopActivitiesLocked()
ActivityStack.resumeTopActivityLocked()
ActivityStack.resumeTopActivityInnerLocked ()
ActivityStack.startSpecificActivityLocked ()

  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);

        r.task.stack.setLaunchTime(r);

        if (app != null && app.thread != null) {
            try {
                if ((r.info.flags&ActivityInfo.FLAG_MULTIPROCESS) == 0
                        || !"android".equals(r.info.packageName)) {
                    // Don't add this if it is a platform component that is marked
                    // to run in multiple processes, because this is actually
                    // part of the framework so doesn't make sense to track as a
                    // separate apk in the process.
                    app.addPackage(r.info.packageName, r.info.applicationInfo.versionCode,
                            mService.mProcessStats);
                }
                realStartActivityLocked(r, app, 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.
        }

        mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
                "activity", r.intent.getComponent(), false, false, true);
    }

如果需要启动的Activity所需要的应用进程是否已经启动,如果没有则执行realStartActivityLocked去启动Activity,否则去启动启动应用进程,相当于一个预启动的过程。

2.4、应用进程创建

关于startProcessLocked怎么执行的,上篇博客分析过,SystemServer进程中Ams通过Socket与Zygote进程进行通信的,Zygote接收到AMS发起的创建进程的请求,会fork出一个子进程,并且反射调用这个进程中ActivityThread的main方法。详情步骤戳我,在应用进程启动之后,ActivityThread的main方法就开始执行了。

三、ActivityThread的main方法执行

在ActivityThread的main方法里调用thread.attach(false);

    public static void main(String[] args) {
        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ActivityThreadMain");
        SamplingProfilerIntegration.start();
        ......

        Process.setArgV0("<pre-initialized>");

        Looper.prepareMainLooper();

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

        if (sMainThreadHandler == null) {
            sMainThreadHandler = thread.getHandler();
        }

        if (false) {
            Looper.myLooper().setMessageLogging(new
                    LogPrinter(Log.DEBUG, "ActivityThread"));
        }

        // End of event ActivityThreadMain.
        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
        Looper.loop();

        throw new RuntimeException("Main thread loop unexpectedly exited");
    }

对于上面main方法,相信很多人都看多很多遍了,接下来重点分析 thread.attach(false)这行代码。

 private void attach(boolean system) {
        sCurrentActivityThread = this;
        mSystemThread = system;
        if (!system) {
             .......

        //获取ActivityManagerService在客户端的代理
            IActivityManager mgr = ActivityManagerNative.getDefault();
            try {

        //实质是调用ActivityManagerService的attachApplication方法,目的是让ActivityManagerService通过ApplicationThread代理对象控制应用进程
                mgr.attachApplication(mAppThread);
            } catch (RemoteException ex) {
            }
        }
    .......
    }

在调用 mgr.attachApplication()的时候,将mAppThread对象传进去了。

   final ApplicationThread mAppThread = new ApplicationThread();

ApplicationThread继承了ApplicationThreadNative, 看一下ApplicationThreadNative里面的方法。

Paste_Image.png

内部调用了ActivityManagerNative.getDefault() .attachApplication,关于ActivityManagerNative已经说了很多了,相当于AMS服务端存根或者代理,其客户端是ActivityManagerNative的内部类ActivityManagerProxy,这里getDefault获取的就是ActivityManagerProxy对象,通过ActivityManagerProxy对象来使用AMS内部的一些服务,包括单不限于启动Activity。所以通过ActivityManagerProxy对象调用attachApplication方法的实质是调用BinderProxy.transact向Binder驱动发送ATTACH_APPLICATION_TRANSACTION命令,binder驱动将处理逻辑从APP应用进程所在的进程切换到AMS所在的SystemServer进程。OK,我们直接看ActivityManagerService的attachApplication方法:

    @Override
    public final void attachApplication(IApplicationThread thread) {
        synchronized (this) {
            int callingPid = Binder.getCallingPid();
            final long origId = Binder.clearCallingIdentity();
            attachApplicationLocked(thread, callingPid);
            Binder.restoreCallingIdentity(origId);
        }
    }
private final boolean attachApplicationLocked(IApplicationThread thread,
            int pid) {
        ProcessRecord app;
        if (pid != MY_PID && pid >= 0) {
            synchronized (mPidsSelfLocked) {
                //通过进程ID,获取进程的记录信息
                app = mPidsSelfLocked.get(pid);
            }
        } else {
            app = null;
        }

        if (app == null) {
            Slog.w(TAG, "No pending application record for pid " + pid
                    + " (IApplicationThread " + thread + "); dropping process");
            EventLog.writeEvent(EventLogTags.AM_DROP_PROCESS, pid);
            if (pid > 0 && pid != MY_PID) {
                //如果没有获取到,需要杀死该进程,MY_PID是系统进程
                Process.killProcessQuiet(pid);

            } else {
                 ......
            return false;
        }

        ......
    //获取进程名称
        final String processName = app.processName;
        try {
            AppDeathRecipient adr = new AppDeathRecipient(
                    app, pid, thread);
            thread.asBinder().linkToDeath(adr, 0);
            app.deathRecipient = adr;
        } catch (RemoteException e) {
            app.resetPackageList(mProcessStats);
            startProcessLocked(app, "link fail", processName);
            return false;
        }

        EventLog.writeEvent(EventLogTags.AM_PROC_BOUND, app.userId, app.pid, app.processName);

    //设置进程的OOM,adj等值

        //还记得上面留下的那个问题吗,AMS是怎么获取到prev.app.thread的呢?就在这,prev.app是ProcessRecord对象,makeActive内部将thread对象赋值给prev.app.thread。可以自己查阅,这样AMS是可以查询进程记录的,进程记录中就有一个app.thread,若AMS要跟Activity通信直接获取prev.app.thread就可以了。
        app.makeActive(thread, mProcessStats);
        app.curAdj = app.setAdj = -100;
        app.curSchedGroup = app.setSchedGroup = Process.THREAD_GROUP_DEFAULT;
        app.forcingToForeground = null;
        updateProcessForegroundLocked(app, false, false);
        app.hasShownUi = false;
        app.debugging = false;
        app.cached = false;
        app.killedByAm = false;

        //将attach之前的超时Meessage移除掉
        mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);

        boolean normalMode = mProcessesReady || isAllowedWhileBooting(app.info);
        List<ProviderInfo> providers = normalMode ? generateApplicationProvidersLocked(app) : null;

          ......
        try {
          ......
            thread.bindApplication(processName, appInfo, providers, app.instrumentationClass,
                    profilerInfo, app.instrumentationArguments, app.instrumentationWatcher,
                    app.instrumentationUiAutomationConnection, testMode, enableOpenGlTrace,
                    isRestrictedBackupMode || !normalMode, app.persistent,
                    new Configuration(mConfiguration), app.compat,
                    getCommonServicesLocked(app.isolated),
                    mCoreSettingsObserver.getCoreSettingsLocked());
            updateLruProcessLocked(app, false, null);
            app.lastRequestedGc = app.lastLowMemory = SystemClock.uptimeMillis();
        } catch (Exception e) {
            // todo: Yikes!  What should we do?  For now we will try to
            // start another process, but that could easily get us in
            // an infinite loop of restarting processes...
            Slog.wtf(TAG, "Exception thrown during bind of " + app, e);

            app.resetPackageList(mProcessStats);
            app.unlinkDeathRecipient();
            startProcessLocked(app, "bind fail", processName);
            return false;
        }

       ......

    // See if the top visible activity is waiting to run in this process...
        if (normalMode) {
            try {
                if (mStackSupervisor.attachApplicationLocked(app)) {
                    didSomething = true;
                }
            } catch (Exception e) {
                Slog.wtf(TAG, "Exception thrown launching activities in " + app, e);
                badApp = true;
            }
        }

        // 执行等待进程而暂时挂起的Service
        if (!badApp) {
            try {
                didSomething |= mServices.attachApplicationLocked(app, processName);
            } catch (Exception e) {
                Slog.wtf(TAG, "Exception thrown starting services in " + app, e);
                badApp = true;
            }
        }

        // 执行等待进程而暂时挂起的广播
        if (!badApp && isPendingBroadcastProcessLocked(pid)) {
            try {
                didSomething |= sendPendingBroadcastsLocked(app);
            } catch (Exception e) {
                // If the app died trying to launch the receiver we declare it 'bad'
                Slog.wtf(TAG, "Exception thrown dispatching broadcasts in " + app, e);
                badApp = true;
            }
        }



        ......

        if (!didSomething) {
        //调整进程优先级adj的值
            updateOomAdjLocked();
        }

        return true;
    }

发现AMS用IApplicationThread对象thread调用了bindApplication,thread实际上就是ApplicationThreadProxy对象。AMS通过ApplicationThreadProxy对象与ActivityThread通信。所以去ApplicationThread中看bindApplication的真正实现。

  public final void bindApplication(String processName, ApplicationInfo appInfo,
                List<ProviderInfo> providers, ComponentName instrumentationName,
                ProfilerInfo profilerInfo, Bundle instrumentationArgs,
                IInstrumentationWatcher instrumentationWatcher,
                IUiAutomationConnection instrumentationUiConnection, int debugMode,
                boolean enableOpenGlTrace, boolean isRestrictedBackupMode, boolean persistent,
                Configuration config, CompatibilityInfo compatInfo, Map<String, IBinder> services,
                Bundle coreSettings) {

            if (services != null) {
                // Setup the service cache in the ServiceManager
                ServiceManager.initServiceCache(services);
            }

            setCoreSettings(coreSettings);
            ......
            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.enableOpenGlTrace = enableOpenGlTrace;
            data.restrictedBackupMode = isRestrictedBackupMode;
            data.persistent = persistent;
            data.config = config;
            data.compatInfo = compatInfo;
            data.initProfilerInfo = profilerInfo;
            sendMessage(H.BIND_APPLICATION, data);
        }

这里又是用H发送了一个消息,是不是很像一个交通枢纽,做转发用的。详细戳我

Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,  "bindApplication");
   AppBindData data = (AppBindData)msg.obj;
    handleBindApplication(data);
    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);

handleBindApplication内部就不分析了,Applcation对象的onCreate方法调用就是在这里面,它内部创建了Applcation对象。

四、Activity周期如何执行

4.1、Activity的onCreate是怎么回调的

回到第二小节的startSpecificActivityLocked方法

  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);

        r.task.stack.setLaunchTime(r);

        if (app != null && app.thread != null) {
            try {
                if ((r.info.flags&ActivityInfo.FLAG_MULTIPROCESS) == 0
                        || !"android".equals(r.info.packageName)) {

                    app.addPackage(r.info.packageName, r.info.applicationInfo.versionCode,
                            mService.mProcessStats);
                }
                realStartActivityLocked(r, app, 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.
        }

        mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
                "activity", r.intent.getComponent(), false, false, true);
    }

在预启动之后,一般我们的应用进程就被孵化来了,直接执行realStartActivityLocked去启动Activity。

在realStartActivityLocked内部调用了如下代码,现在你应该知道 app.thread是什么了。

 app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
                    System.identityHashCode(r), r.info, new Configuration(mService.mConfiguration),
                    new Configuration(stack.mOverrideConfig), r.compat, r.launchedFromPackage,
                    task.voiceInteractor, app.repProcState, r.icicle, r.persistentState, results,
                    newIntents, !andResume, mService.isNextTransitionForward(), profilerInfo);

直接到scheduleLaunchActivity真正实现,它的真正实现是在Applciation中的。

  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<ResultInfo> pendingResults, List<ReferrerIntent> pendingNewIntents,
                boolean notResumed, boolean isForward, ProfilerInfo profilerInfo) {

            updateProcessState(procState, false);

            ActivityClientRecord r = new ActivityClientRecord();

            r.token = token;
            r.ident = ident;
            r.intent = intent;
            r.referrer = referrer;
            r.voiceInteractor = voiceInteractor;
            r.activityInfo = info;
            r.compatInfo = compatInfo;
            r.state = state;
            r.persistentState = persistentState;

            r.pendingResults = pendingResults;
            r.pendingIntents = pendingNewIntents;

            r.startsNotResumed = notResumed;
            r.isForward = isForward;

            r.profilerInfo = profilerInfo;

            r.overrideConfig = overrideConfig;
            updatePendingConfiguration(curConfig);

            sendMessage(H.LAUNCH_ACTIVITY, r);
        }

经过一堆的变量赋值之后,又通过H发送了一个消息LAUNCH_ACTIVITY,H在收到这个消息之后,执行下面。

  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);
 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
 private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent) {
        // If we are getting ready to gc after going to the background, well
        // we are back active so skip it.
        unscheduleGcIdler();
        mSomeActivitiesChanged = true;

        if (r.profilerInfo != null) {
            mProfiler.setProfiler(r.profilerInfo);
            mProfiler.startProfiling();
        }

        // Make sure we are running with the most recent config.
        handleConfigurationChanged(null, null);

        if (localLOGV) Slog.v(
            TAG, "Handling launch of " + r);

        // Initialize before creating the activity
        WindowManagerGlobal.initialize();

         //一个 perform开头的方法,启动Activity
        Activity a = performLaunchActivity(r, customIntent);

        if (a != null) {
            r.createdConfig = new Configuration(mConfiguration);
            Bundle oldState = r.state;
            //Launch
            handleResumeActivity(r.token, false, r.isForward,
                    !r.activity.mFinished && !r.startsNotResumed);

            if (!r.activity.mFinished && r.startsNotResumed) {

                try {
                    r.activity.mCalled = false;

                    mInstrumentation.callActivityOnPause(r.activity);

                    if (r.isPreHoneycomb()) {
                        r.state = oldState;
                    }
                    if (!r.activity.mCalled) {
                        throw new SuperNotCalledException(
                            "Activity " + r.intent.getComponent().toShortString() +
                            " did not call through to super.onPause()");
                    }

                } catch (SuperNotCalledException e) {
                    throw e;

                } catch (Exception e) {
                     .....
                }
                r.paused = true;
            }
         .....
        }
    }

这个方法会将Activity创建出来。

  private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {

        ActivityInfo aInfo = r.activityInfo;
         r.activityInfo.targetActivity);

        ......
        Activity activity = null;
        try {
            java.lang.ClassLoader cl = r.packageInfo.getClassLoader();

            activity = mInstrumentation.newActivity(
                    cl, component.getClassName(), r.intent);
          .......
        } catch (Exception e) {
             .......
        }

       Application app = r.packageInfo.makeApplication(false, mInstrumentation);
        if (localLOGV) Slog.v(TAG, "Performing launch of " + r);
        if (activity != null) {     
        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);
             .......
    //Activity的create方法执行
          if (r.isPersistable()) {
                    mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
                } else {
                    mInstrumentation.callActivityOnCreate(activity, r.state);
                }
   .......

        r.activity = activity;
                r.stopped = true;
                if (!r.activity.mFinished) {
                //Activity的start方法执行
                    activity.performStart();
                    r.stopped = false;
                }
        mActivities.put(r.token, r);

        return activity;
    }

反射创建Activity,为啥要用反射呢,此处搞不清楚。

    public Activity newActivity(ClassLoader cl, String className,
            Intent intent)
            throws InstantiationException, IllegalAccessException,
            ClassNotFoundException {
        return (Activity)cl.loadClass(className).newInstance();
    }

解析来mInstrumentation调用callActivityOnCreate方法。

   public void callActivityOnCreate(Activity activity, Bundle icicle,
            PersistableBundle persistentState) {
        prePerformCreate(activity);
        activity.performCreate(icicle, persistentState);
        postPerformCreate(activity);
    }
  final void performCreate(Bundle icicle) {
        onCreate(icicle);
        mActivityTransitionState.readState(icicle);
        performCreateCommon();
    }

onCreate方法在此处被调用了。

4.2、Activity的onStart是怎么回调的

在performLaunchActivity中调用了callActivityOnCreate之后,又会调用 activity.performStart()

 final void performStart() {
        mActivityTransitionState.setEnterActivityOptions(this, getActivityOptions());
        mFragments.noteStateNotSaved();
        mCalled = false;
        mFragments.execPendingActions();
        mInstrumentation.callActivityOnStart(this);
        if (!mCalled) {
            throw new SuperNotCalledException(
                "Activity " + mComponent.toShortString() +
                " did not call through to super.onStart()");
        }
        mFragments.dispatchStart();
        mFragments.reportLoaderStart();
        mActivityTransitionState.enterReady(this);
    }
 public void callActivityOnStart(Activity activity) {
        activity.onStart();
    }

到此处start方法又被调用了。

4.3、Activity的onResume是怎么回调的

handleLaunchActivity方法中,在调用performLaunchActivity之后,调用了handleResumeActivity方法。

ActivityThread.handleResumeActivity()
ActivityThread.handleResumeActivity()
Activity.performResume()
 Instrumentation.callActivityOnResume();
    public void callActivityOnResume(Activity activity) {
        activity.mResumed = true;
        activity.onResume();

        if (mActivityMonitors != null) {
            synchronized (mSync) {
                final int N = mActivityMonitors.size();
                for (int i=0; i<N; i++) {
                    final ActivityMonitor am = mActivityMonitors.get(i);
                    am.match(activity, activity, activity.getIntent());
                }
            }
        }
    }

到此Activity的onResume方法被调用,onPause方法已经讲解过,关于onStop,onDestory一样的套路分析。

五、总结

关于Activity的启动过程分析,三篇文章都分析完了,现在以一张图总结一下。

  • 启动一个Activity的方式有多种,都是通过向Ams发送startActivity请求

  • Ams在启动Activity的时候,会判断目标进程有没有被创建,没有创建的话,向zygote进程发送创建进程的请求;

  • Zygote进程fork出新的子进程,即App进程;

  • App进程,通过Binder IPC向sytem_server进程发起attachApplication请求;

  • AMS所在的SystemServer进程在收到请求后,进行一系列准备工作后,再通过binder IPC向App进程发送scheduleLaunchActivity请求;

  • App进程的binder线程(ApplicationThread)在收到请求后,通过handler向主线程发送LAUNCH_ACTIVITY消息;

  • 主线程在收到Message后,通过发射机制创建目标Activity,并回调Activity.onCreate()等方法。

上图大致说明了一个Activity的启动流程, 重点在于把握Binder的通信原理,接着弄清楚APP进程,SystemServer进程,Zygote进程是怎么互相通信的。seeyou!

参考博客:
http://gityuan.com/2016/03/12/start-activity/

作者:u013263323 发表于2017/3/8 14:53:38 原文链接
阅读:3 评论:0 查看评论

Viewing all articles
Browse latest Browse all 5930

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>