Android 进阶 - Activity应用启动分析

在写本文之前,写了一篇《Android 入门 -应用启动分析》,但那篇文章只简单的钻入了源代码分析的圈圈里,文章很长,但条理不够清晰。现在,重写一篇,并将进程启动提炼出来另写了一篇,详见《Android进阶 - 进程启动分析》。
Andorid系统启动后,就可以使用系统中的应用程序了,Android的应用程序的后缀是:apk,分为系统应用和用户应用,系统应用可在编译源码时,打包发行,用户应用则可以通过应用市场等来下载安装。Launcher本身也是一个系统应用,在《Android入门-系统启动简介》提到,SystemServer是通过:ActivityStackSupervisor.startActivityLocked()来启动主屏幕应用的。其实,所有的Android应用都可以通过这种方法启动。

1、Activity应用启动的几个阶段

Activity应用启动大致可以分为以下几个阶段:
  1. 准备阶段:做进程启动前的准备工作。
  2. 进程启动阶段:通过Zygote启动进程。(当应用已经启动时,此步骤略)
  3. Activity启动阶段:在新的进程里,启动Activity。
本文重点说明第1阶段和第3阶段,进程启动阶段参见前一篇文章《Android 进阶 - 进程启动分析》。

2. 准备阶段

此阶段主要是做启动入口至进程启动之前的处理工作,通过不同的入口,启动Activity,需要做一些不同的处理。Home主屏幕应用(Launcher)由于是在Android系统启动时,直接通过ActivityManagerService启动的,不用走一次Binder进程间通讯的流程,但在Launcher应用或是其他应用里启动一个应用时,则需要通过Binder驱动程序,进入到ActivityManagerService服务时来启动,所以,要启动过程复杂一点。

2.1 Launcher启动准备

《Android入门 -系统启动简介》已经分析了,Launcher的启动是通过ActivityManagerService.startHomeActivityLocked启动的:
  1. startHomeActivityLocked:
    frameworks/base/services/java/com/android/server/am/ActivityManagerService.java:
    //获取主屏幕Intent
    Intent getHomeIntent() {
        Intent intent = new Intent(mTopAction, mTopData != null ? Uri.parse(mTopData) : null);
        intent.setComponent(mTopComponent);
        if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
            intent.addCategory(Intent.CATEGORY_HOME);
        }
        return intent;
    }
    boolean startHomeActivityLocked(int userId) {
        ...
        // 获取主屏幕的Intent
        Intent intent = getHomeIntent();
        // 获取主屏幕的Activity信息(如:包名,Activity名,应用信息,进程名等)
        ActivityInfo aInfo =
            resolveActivityInfo(intent, STOCK_PM_FLAGS, userId);
        if (aInfo != null) {
            // 设置主屏幕Intent的组件信息
            intent.setComponent(new ComponentName(
                    aInfo.applicationInfo.packageName, aInfo.name));
            // Don't do this if the home app is currently being
            // instrumented.
            aInfo = new ActivityInfo(aInfo);
            aInfo.applicationInfo = getAppInfoForUser(aInfo.applicationInfo, userId);
            // 获取主屏幕应用的进程信息
            ProcessRecord app = getProcessRecordLocked(aInfo.processName,
                    aInfo.applicationInfo.uid, true);
            if (app == null || app.instrumentationClass == null) {
            	// 假如主屏幕应用进程未启动,则启动
                intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);
                mStackSupervisor.startHomeActivity(intent, aInfo);
            }
        }
    
        return true;
    }
    
  2. startActivityLocked:
    frameworks/base/services/java/com/android/server/am/ActivityStackSupervisor.java:
    void startHomeActivity(Intent intent, ActivityInfo aInfo) {
        moveHomeToTop();
        startActivityLocked(null, intent, null, aInfo, null, null, 0, 0, 0, null, 0,
                null, false, null);
    }
    
可以看出,ActivityManagerService是通过调用ActivityStackSupervisor.startActivityLocked()来启动主屏幕应用。

2.2、一般应用启动准备流程

这里,我们先创建一个HelloAndroid的应用,再创建一个TestCallApp的应用,尝试在TestCallApp里,启动HelloAndroid应用。
2.2.1、创建HelloAndroid应用

在Eclipse里,NewProject->Android ApplicationProject,取名:HelloAndroid,package名为:com.helloandroid。按向导一直Next,最后点击finish。

打开AndroidManifest.xml:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.helloandroid" android:versioncode="1" android:versionname="1.0">

    <uses-sdk android:minsdkversion="19" android:targetsdkversion="19">

    <application android:allowbackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme">
        <activity android:name="com.helloandroid.MainActivity" android:label="@string/app_name">
            <intent-filter>
                <action android:name="android.intent.action.MAIN">
                <action android:name="com.helloandroid.HELLO">
                <category android:name="android.intent.category.DEFAULT">
                <category android:name="android.intent.category.LAUNCHER">
            </category></category></action></action></intent-filter>
        </activity>
    </application>
</uses-sdk></manifest>

intent-filter下面已经有一个名为“android.intent.action.MAIN”的action和一个名为“android.intent.category.LAUNCHER”的category,这是用于在Launcher里点击用户图标来启动应用的。我们在intent-filter下新增一个名为“com.helloandroid.HELLO”的action和一个名为“android.intent.category.DEFAULT”的category,这样做是为了方便其他程序调用。本章暂不详细讨论Intent。

点击Run,安装并运行HelloAndroid应用。

2.2.2、创建TestCallApp应用

创建应用的方法同上,名称用:TestCallApp,包名为:com.testcallapp。打开fragment_main.xml,转至GraphicalLayout,拖一个Button放到界面上,ID为call_button。

转至MainActivity.java:

...
/**
 * A placeholder fragment containing a simple view.
 */
public static class PlaceholderFragment extends Fragment {

    public PlaceholderFragment() {
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        View rootView = inflater.inflate(R.layout.fragment_main, container, false);
        // 加入下面代码
        Button b = (Button) rootView.findViewById(R.id.call_button);
        if (b != null)
            b.setOnClickListener(new OnClickListener() {

                @Override
                public void onClick(View v) {
                    Intent intent = new Intent();
                    intent.setAction("com.helloandroid.HELLO");
                    startActivity(intent);
                }
            });
        return rootView;
    }
}
...

上面是在Activity里内嵌了一个Fragment碎片,如果没用Fragment,可以在Activity.OnCreate里写上面的代码。

点击Run,运行并安装此程序。点击”Call“按钮,即可启动HelloAndroid应用。

此案例说明了如何从一个应用里启动另一个应用,也是用Intent,通过Activity.startActivity()函数来调用。

2.3、流程图

由于一般应用启动流程要比Home应用启动复杂,这里我们以一般应用启动流程,来说明其进程启动之前的准备工作。

在上图中我们可以知道,Home应用启动流程是在1.3.1.1.2.1:startActivityLocket步骤开始的,后面的流程与一般应用的启动流程相同。

2.4 关键流程解析 

上面的流程图比较清晰,这里仅选取少数几处较为关键的函数代码分析。
2.4.1 Binder通信
Binder的具体实现将忽略,将作用为专题文章来讨论。当流程走到mInstrumentation.execStartActivity时:
frameworks/base/core/java/android/app/Instrumentation.java
    ...
    public ActivityResult execStartActivity(
            Context who, IBinder contextThread, IBinder token, Activity target,
            Intent intent, int requestCode, Bundle options) {
        ...
        try {
            intent.migrateExtraStreamToClipData();
            intent.prepareToLeaveProcess();
            int result = ActivityManagerNative.getDefault()
                .startActivity(whoThread, who.getBasePackageName(), intent,
                        intent.resolveTypeIfNeeded(who.getContentResolver()),
                        token, target != null ? target.mEmbeddedID : null,
                        requestCode, 0, null, null, options);
            checkStartActivityResult(result, intent);
        } catch (RemoteException e) {
        }
        return null;
    }
    ...

流程走到这里,突然看不到源码了,因为IActivityManager是一个接口,通过调用IActivityManager.startActivity函数,来启动Activity。那么,IActivityManager的实现类在哪?先来看看ActivityManagerNative.getDefault()干了什么。

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

    static public IActivityManager asInterface(IBinder obj) {
        if (obj == null) {
            return null;
        }
        IActivityManager in =
            (IActivityManager)obj.queryLocalInterface(descriptor);
        if (in != null) {
            return in;
        }

        return new ActivityManagerProxy(obj);
    }
	...
    static public IActivityManager getDefault() {
        return gDefault.get();
    }
    ...
    private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>() {
        protected IActivityManager create() {
            IBinder b = ServiceManager.getService("activity");
            if (false) {
                Log.v("ActivityManager", "default service binder = " + b);
            }
            IActivityManager am = asInterface(b);
            if (false) {
                Log.v("ActivityManager", "default service = " + am);
            }
            return am;
        }
    };

ActivityManagerNative.gDefault是一个私有的单例模式运行的成员变量,保存当前默认的IActivityManager,从create代码可以看出,gDefault是"activity"服务的一个通信代理,即:ActivityManagerProxy,通过IBinder与ActivityManagerService通信,进入到ActivityManagerService.startActivityLocked。

2.4.2 ActivityStatck.startActivityLocked
frameworks/base/services/java/com/android/server/am/ActivityStack.java
final void startActivityLocked(ActivityRecord r, boolean newTask,
        boolean doResume, boolean keepCurTransition, Bundle options) {
    TaskRecord rTask = r.task;
    final int taskId = rTask.taskId;
    if (taskForIdLocked(taskId) == null || newTask) {
    	// 如果是新任务,则将任务插入到任务列表顶端
        // Last activity in task had been removed or ActivityManagerService is reusing task.
        // Insert or replace.
        // Might not even be in.
        insertTaskAtTop(rTask);
        mWindowManager.moveTaskToTop(taskId);
    }
    TaskRecord task = null;
    if (!newTask) {
        ...
    }
    ...

    task = r.task;

    // Slot the activity into the history stack and proceed
    if (DEBUG_ADD_REMOVE) Slog.i(TAG, "Adding activity " + r + " to stack to task " + task,
            new RuntimeException("here").fillInStackTrace());
    // 将Activity插到任务的Activities顶端,一个任务可以有多个Activities
    task.addActivityToTop(r);
	// 标记Activity已经在历史记录中
    r.putInHistory();
    r.frontOfTask = newTask;
    if (!isHomeStack() || numActivities() > 0) {
        // 非home下的窗口处理,略
        ...
    } else {
        // home下的窗口处理,涉及锁屏等,略
        ...
    }
    if (VALIDATE_TOKENS) {
        validateAppTokensLocked();
    }

    if (doResume) {
    	// 恢复或启动顶层的Activity,本函数之前已经将Activity置入顶层
        mStackSupervisor.resumeTopActivitiesLocked();
    }
}

本函数先将Activity插入到Activities的顶端,再调用resumeTopActivitiesLocked函数,走到ActivityStack.resumtTopActivityLocked。

2.4.3 ActivityStackSupervisor.resumeTopActivitiesLocked:
frameworks/base/services/java/com/android/server/am/ActivityStack.java
final boolean resumeTopActivityLocked(ActivityRecord prev) {
    return resumeTopActivityLocked(prev, null);
}
final boolean resumeTopActivityLocked(ActivityRecord prev, Bundle options) {
    if (ActivityManagerService.DEBUG_LOCKSCREEN) mService.logLockScreen("");
	// 找到顶层的ActivityRecord
    // Find the first activity that is not finishing.
    ActivityRecord next = topRunningActivityLocked(null);

    // Remember how we'll process this pause/resume situation, and ensure
    // that the state is reset however we wind up proceeding.
    final boolean userLeaving = mStackSupervisor.mUserLeaving;
    mStackSupervisor.mUserLeaving = false;

    if (next == null) {
    	// 此处启动Launcher,在上一篇文章有描述,不过,经过一翻流转,最终还是会回到本函数,但此时next不是null了。Android源码,哎。。。
        ...
    }
	...
    if (next.app != null && next.app.thread != null) {
    	// 应用已经启动情况,有可能会重启动应用,此处不分析
        ...

    } else {
        ...
        mStackSupervisor.startSpecificActivityLocked(next, true, true);
    }
    if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
    return true;
}

上面的函数逻辑非常复杂,有许多的return语句,这些return之后,经过一翻流转有可能又进入此函数,进入另一个判断分支。本文不详细分析Activity的各种复杂管理,只讨论如何启动,所以,略去了这许多代码。

2.4.4 ActivityStackSupervisor.startSpecificActivityLocked:
frameworks/base/services/java/com/android/server/am/ActivityStackSupervisor.java
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) {
        // 如果进程已经运行。。。当然,在一个应用内启动自己的Activity,肯定会进入此段代码
		try {
            // 直接启动Activity,
            realStartActivityLocked(r, app, andResume, checkConfig);
            return;
        } catch (RemoteException e) {
            Slog.w(TAG, "Exception when starting activity "
                    + r.intent.getComponent().flattenToShortString(), e);
        }
    }
	//启动进程
    mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
            "activity", r.intent.getComponent(), false, false, true);
}
如果应用已经运行,则直接进入Activity启动阶段,否则,进入进程启动阶段。
说明:如何判断应用是否已经运行,这个在前面的源代码并未详细分析,本文也不准备详细分析,今后如果有项目的需要,再来继续深入研究,目前,了解到这么多足够了,因为如果是单实例应用,分析的必要性不大,而多实例(MULTI)应用并不多见。

3 进程启动阶段

略,见《Android 进阶 - 进程启动分析》。

4 Activity启动阶段

在《Android 进阶 -进程启动分析》一文中,最后指出,进程启动,并将进程的thread指定到新创建的ActivityThread之后,会首先尝试将进程作为应用来启动,即调用ActivityStackSupervisor.attachApplicationLocked来连接进程。我们接着这来分析。

4.1 流程图


4.2 关键流程解析

本节的流程与Looper有很大的相关性,在ActivityThread内部的通信,是采用Looper的异步消息队列通讯机制。
上图的流程,是承接新进程的情况下,画的。如果是应用已经启动进程情况,可直接从3.1:realStartActivityLocked步骤开始看。
4.2.1 发送H.LAUNCH_ACTICITY消息
流程走至ActivityStackSupervisor.realStartActivityLocked,见代码:
frameworks/base/services/java/com/android/server/am/ActivityStackSupervisor.java
boolean attachApplicationLocked(ProcessRecord app, boolean headless) throws Exception {
    boolean didSomething = false;
    final String processName = app.processName;
    // 找到app对应的ActivityRecord,并调用realStartActivityLocked启动Activity。
    for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
        final ActivityStack stack = mStacks.get(stackNdx);
        if (!isFrontStack(stack)) {
            continue;
        }
        ActivityRecord hr = stack.topRunningActivityLocked(null);
        if (hr != null) {
            if (hr.app == null && app.uid == hr.info.applicationInfo.uid
                    && processName.equals(hr.processName)) {
                try {
                    if (headless) {
                        Slog.e(TAG, "Starting activities not supported on headless device: "
                                + hr);
                    } else if (realStartActivityLocked(hr, app, true, true)) {
                        didSomething = true;
                    }
                } catch (Exception e) {
                    Slog.w(TAG, "Exception in new application when starting activity "
                          + hr.intent.getComponent().flattenToShortString(), e);
                    throw e;
                }
            }
        }
    }
    if (!didSomething) {
        ensureActivitiesVisibleLocked(null, 0);
    }
    return didSomething;
}
...
final boolean realStartActivityLocked(ActivityRecord r,
        ProcessRecord app, boolean andResume, boolean checkConfig)
        throws RemoteException {
	...

    r.app = app;
    app.waitingToKill = null;
    r.launchCount++;
    r.lastLaunchTime = SystemClock.uptimeMillis();
	...
    final ActivityStack stack = r.task.stack;
    try {
        if (app.thread == null) {
            throw new RemoteException();
        }
        ...
        // 启动Activity
        app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
                System.identityHashCode(r), r.info,
                new Configuration(mService.mConfiguration), r.compat,
                app.repProcState, r.icicle, results, newIntents, !andResume,
                mService.isNextTransitionForward(), profileFile, profileFd,
                profileAutoStop);
		...

    } catch (RemoteException e) {
        ...
        throw e;
    }
	...

    return true;
}
在《Android 进阶 - 进程启动分析》一文,已经说明,app.thread是一个IApplicationThread的Binder远程接口,可以通过app.thread,经由Binder进入Activity的thread服务端对象,即ApplicationThread类的实例,所以,app.thread是ActivityManagerService反调Activity应用的桥梁。app.thread.scheduleLaunchActivity经由Binder,进入到ApplicationThread.scheduleLaunchActivity函数中。
frameworks/base/core/java/android/app/ActivityThread.java
public class ActivityThread{
    // mH是一个H类实例
	final H mH = new H();
	...
	// H类继承自android.os.Handler类。
	private class H extends Handler {
	}
	...
    class ApplicationThread{
	    ...
		public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
		        ActivityInfo info, Configuration curConfig, CompatibilityInfo compatInfo,
		        int procState, Bundle state, List<ResultInfo> pendingResults,
		        List<Intent> pendingNewIntents, boolean notResumed, boolean isForward,
		        String profileName, ParcelFileDescriptor profileFd, boolean autoStopProfiler) {
		
		    updateProcessState(procState, false);
		
		    ActivityClientRecord r = new ActivityClientRecord();
		
		    r.token = token;
		    r.ident = ident;
		    r.intent = intent;
		    r.activityInfo = info;
		    r.compatInfo = compatInfo;
		    r.state = state;
		
		    r.pendingResults = pendingResults;
		    r.pendingIntents = pendingNewIntents;
		
		    r.startsNotResumed = notResumed;
		    r.isForward = isForward;
		
		    r.profileFile = profileName;
		    r.profileFd = profileFd;
		    r.autoStopProfiler = autoStopProfiler;
		
		    updatePendingConfiguration(curConfig);
		
		    sendMessage(H.LAUNCH_ACTIVITY, r);
		}
		....
	    private void sendMessage(int what, Object obj) {
	        sendMessage(what, obj, 0, 0, false);
	    }
	    ...
	    private void sendMessage(int what, Object obj, int arg1, int arg2, boolean async) {
	        if (DEBUG_MESSAGES) Slog.v(
	            TAG, "SCHEDULE " + what + " " + mH.codeToString(what)
	            + ": " + arg1 + " / " + obj);
	        Message msg = Message.obtain();
	        msg.what = what;
	        msg.obj = obj;
	        msg.arg1 = arg1;
	        msg.arg2 = arg2;
	        if (async) {
	            msg.setAsynchronous(true);
	        }
	        // 通过mH发送消息。
	        mH.sendMessage(msg);
	    }
	}
}

然后,通过Looper机制,发送H.LAUNCH_ACTICITY消息。

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

public Handler{
	...
	public final boolean sendMessage(Message msg)
    {
        return sendMessageDelayed(msg, 0);
    }
    ...
    public final boolean sendMessageDelayed(Message msg, long delayMillis)
    {
        if (delayMillis < 0) {
            delayMillis = 0;
        }
        return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
    }
    ...
    public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
        MessageQueue queue = mQueue;
        if (queue == null) {
            RuntimeException e = new RuntimeException(
                    this + " sendMessageAtTime() called with no mQueue");
            Log.w("Looper", e.getMessage(), e);
            return false;
        }
        return enqueueMessage(queue, msg, uptimeMillis);
    }
    ...
    // 通过前面的调用,最终进入本函数,执行消息入队
    private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
        // 将消息的target,指向自己,这样在Looper.loop中可以调用msg.target.dispatchMessage来回调本Handle的消息处理
        msg.target = this;
        if (mAsynchronous) {
            msg.setAsynchronous(true);
        }
        return queue.enqueueMessage(msg, uptimeMillis);
    }
}
本函数流程比较简单,创建一个ActivityClientRecord,然后,发送LAUNCH_ACTIVITY消息,启动一个Activity。消息通过mH发送,走到android.os.Handler.enqueueMessage函数,完成消息的入队,具体见上面的源代码注释。有关Looper消息的内容,参见《Android 进阶 - Looper进程内通信》一文。
上面的代码,其实只是将msg放入到mQueue队列中。尽管这里用的mQueue队列,但并不是异步处理,因为此段代码的在main线程中执行。后面的Looper.loop()函数会处理这个消息的。
4.2.2 处理H.LAUNCH_ACTIVITY
前面已经将H.LAUNCH_ACTICITY消息发送给Looper.mainLooper,接下来,就是处理消息了。在ActivityThread.main()函数中,调用attach函数()之后,会执行Looper.loop(),进入消息循环,处理消息。由于之前的消息是通过mH发送,所以,消息的处理,最终会进入H.handleMessage中,这在Looper进程内通讯一文中有详细描述。
frameworks/base/core/java/android/app/ActivityThread.java
public final class ActivityThread {
	...
	final H mH = new H();
	...
	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: {
                	// 处理H.LAUNCH_ACTIVITY消息
                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
                    ActivityClientRecord r = (ActivityClientRecord)msg.obj;

                    r.packageInfo = getPackageInfoNoCheck(
                            r.activityInfo.applicationInfo, r.compatInfo);
                    handleLaunchActivity(r, null);
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                } break;
            ...
            }
            ...
        }
	}
	...
	private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent) {
        ...
        Activity a = performLaunchActivity(r, customIntent);

        if (a != null) {
            r.createdConfig = new Configuration(mConfiguration);
            Bundle oldState = r.state;
            handleResumeActivity(r.token, false, r.isForward,
                    !r.activity.mFinished && !r.startsNotResumed);
			...
        } else {
            ...
        }
    }
    ...
    private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
        // System.out.println("##### [" + System.currentTimeMillis() + "] ActivityThread.performLaunchActivity(" + r + ")");

        ActivityInfo aInfo = r.activityInfo;
        ...
        Activity activity = null;
        try {
            java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
            // 创建新的Activity实例
            activity = mInstrumentation.newActivity(
                    cl, component.getClassName(), r.intent);
            StrictMode.incrementExpectedActivityCount(activity.getClass());
            r.intent.setExtrasClassLoader(cl);
            if (r.state != null) {
                r.state.setClassLoader(cl);
            }
        } catch (Exception e) {
            if (!mInstrumentation.onException(activity, e)) {
                throw new RuntimeException(
                    "Unable to instantiate activity " + component
                    + ": " + e.toString(), e);
            }
        }

        try {
            Application app = r.packageInfo.makeApplication(false, mInstrumentation);

            if (localLOGV) Slog.v(TAG, "Performing launch of " + r);
            if (localLOGV) Slog.v(
                    TAG, r + ": app=" + app
                    + ", appName=" + app.getPackageName()
                    + ", pkg=" + r.packageInfo.getPackageName()
                    + ", comp=" + r.intent.getComponent().toShortString()
                    + ", dir=" + r.packageInfo.getAppDir());

            if (activity != null) {
            	// 为Activity创建上下文
                Context appContext = createBaseContextForActivity(r, activity);
                CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());
                Configuration config = new Configuration(mCompatConfiguration);
                if (DEBUG_CONFIGURATION) Slog.v(TAG, "Launching activity "
                        + r.activityInfo.name + " with config " + config);
                // 将Activity与上下文连接
                activity.attach(appContext, this, getInstrumentation(), r.token,
                        r.ident, app, r.intent, r.activityInfo, title, r.parent,
                        r.embeddedID, r.lastNonConfigurationInstances, config);

                if (customIntent != null) {
                    activity.mIntent = customIntent;
                }
                r.lastNonConfigurationInstances = null;
                activity.mStartedActivity = false;
                int theme = r.activityInfo.getThemeResource();
                if (theme != 0) {
                    activity.setTheme(theme);
                }

                activity.mCalled = false;
                // 发送Activity.OnCreate事件,在这里可调用用户定义的事件。
                mInstrumentation.callActivityOnCreate(activity, r.state);
                ...
            }
            r.paused = true;

            mActivities.put(r.token, r);

        } catch (SuperNotCalledException e) {
            throw e;

        } catch (Exception e) {
            if (!mInstrumentation.onException(activity, e)) {
                throw new RuntimeException(
                    "Unable to start activity " + component
                    + ": " + e.toString(), e);
            }
        }

        return activity;
    }
    ...
}

5. 结语

将Activity分为几个阶段来分析,就将原本复杂的逻辑简单化了,并且同时解决了启动应用内部的Activity的情况分析,其实,就只是少了一个进程启动的环节。
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值