天天看點

Android startActivity源碼詳解

轉載請标明出處   Android源碼詳解目錄

在Android頁面跳轉的時候,我們一般都會調用startActivity(Intent intent),調用之後就會跳轉到下一個頁面了,究竟是怎麼跳轉的,今天我們結合源碼來給大家分析一下,我們知道,Android的Activity的建立,啟動都非常複雜,很多類都比較龐大,我們把主要的樹幹理清就行了,不必過多的糾結于它的繁枝細節,下面我就結合源碼為大家一一分析,我們進入源碼

/**
     * Same as {@link #startActivity(Intent, Bundle)} with no options
     * specified.
     *
     * @param intent The intent to start.
     *
     * @throws android.content.ActivityNotFoundException
     *
     * @see {@link #startActivity(Intent, Bundle)}
     * @see #startActivityForResult
     */
    @Override
    public void startActivity(Intent intent) {
        startActivity(intent, null);
    }
           

調用了另一個重構方法,我們繼續

@Override
    public void startActivity(Intent intent, Bundle options) {
        if (options != null) {
            startActivityForResult(intent, -1, options);
        } else {
            // Note we want to go through this call for compatibility with
            // applications that may have overridden the method.
            startActivityForResult(intent, -1);
        }
    }
           

其實上面兩個方法最終調用的都是同一個方法,我們直接看它的源碼,注釋比較多,我就不在貼出

public void startActivityForResult(Intent intent, int requestCode, Bundle options) {
        if (mParent == null) {
            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());
            }
            if (requestCode >= 0) {
                // If this start is requesting a result, we can avoid making
                // the activity visible until the result is received.  Setting
                // this code during onCreate(Bundle savedInstanceState) or onResume() will keep the
                // activity hidden during this time, to avoid flickering.
                // This can only be done when a result is requested because
                // that guarantees we will get information back when the
                // activity is finished, no matter what happens to it.
                mStartedActivity = true;
            }

            final View decor = mWindow != null ? mWindow.peekDecorView() : null;
            if (decor != null) {
                decor.cancelPendingInputEvents();
            }
            // TODO Consider clearing/flushing other event sources and events for child windows.
        } else {
            if (options != null) {
                mParent.startActivityFromChild(this, intent, requestCode, options);
            } else {
                // Note we want to go through this method for compatibility with
                // existing applications that may have overridden it.
                mParent.startActivityFromChild(this, intent, requestCode);
            }
        }
    }
           

我們看主要分支,我們隻看mParent ==null的那部分,如果ar!=null就會調用下面一個回調方法,也是我們平時常用的

@Override
	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
	// TODO Auto-generated method stub
	super.onActivityResult(requestCode, resultCode, data);
}
           

下面我們主要來分析mInstrumentation.execStartActivity這行代碼,我們找到他的源碼檢視

public ActivityResult execStartActivity(
        Context who, IBinder contextThread, IBinder token, Fragment target,
        Intent intent, int requestCode, Bundle options) {
        IApplicationThread whoThread = (IApplicationThread) contextThread;
        if (mActivityMonitors != null) {
            synchronized (mSync) {
                final int N = mActivityMonitors.size();
                for (int i=0; i<N; i++) {
                    final ActivityMonitor am = mActivityMonitors.get(i);
                    if (am.match(who, null, intent)) {
                        am.mHits++;
                        if (am.isBlocking()) {
                            return requestCode >= 0 ? am.getResult() : null;
                        }
                        break;
                    }
                }
            }
        }
        try {
            intent.migrateExtraStreamToClipData();
            intent.prepareToLeaveProcess();
            int result = ActivityManagerNative.getDefault()
                .startActivity(whoThread, who.getBasePackageName(), intent,
                        intent.resolveTypeIfNeeded(who.getContentResolver()),
                        token, target != null ? target.mWho : null,
                        requestCode, 0, null, null, options);
            checkStartActivityResult(result, intent);
        } catch (RemoteException e) {
        }
        return null;
    }
           

我們主要看最後幾行,我們知道ActivityManagerNative是一個抽象類,并且繼承了Binder,我們來看一下他的源碼

public abstract class ActivityManagerNative extends Binder implements IActivityManager
{
    /**
     * Cast a Binder object into an activity manager interface, generating
     * a proxy if needed.
     */
    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);
    }

    /**
     * Retrieve the system's default/global activity manager.
     */
    static public IActivityManager getDefault() {
        return gDefault.get();
    }
    …………………………
}
           

在上面我們還看到checkStartActivityResult這個方法,我們來看一下他的源碼

/*package*/ 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);
                …………………………
        }
    }
           

看到沒,這裡面就有我們經常見到的,類沒找到或者沒有在AndroidManifest中注冊的異常,我們再來看一下IActivityManager的源碼,

public interface IActivityManager extends IInterface {
    public int startActivity(IApplicationThread caller, String callingPackage,
            Intent intent, String resolvedType, IBinder resultTo, String resultWho,
            int requestCode, int flags, String profileFile,
            ParcelFileDescriptor profileFd, Bundle options) throws RemoteException;
    public int startActivityAsUser(IApplicationThread caller, String callingPackage,
            Intent intent, String resolvedType, IBinder resultTo, String resultWho,
            int requestCode, int flags, String profileFile,
            ParcelFileDescriptor profileFd, Bundle options, int userId) throws RemoteException;
    public WaitResult startActivityAndWait(IApplicationThread caller, String callingPackage,
            Intent intent, String resolvedType, IBinder resultTo, String resultWho,
            int requestCode, int flags, String profileFile,
            ParcelFileDescriptor profileFd, Bundle options, int userId) throws RemoteException;
    		…………………………
    public Intent registerReceiver(IApplicationThread caller, String callerPackage,
            IIntentReceiver receiver, IntentFilter filter,
            String requiredPermission, int userId) throws RemoteException;
    public void unregisterReceiver(IIntentReceiver receiver) throws RemoteException;
    		…………………………  
    public ComponentName startService(IApplicationThread caller, Intent service,
            String resolvedType, int userId) throws RemoteException;
    public int stopService(IApplicationThread caller, Intent service,
            String resolvedType, int userId) throws RemoteException;
    		…………………………
    public int bindService(IApplicationThread caller, IBinder token,
            Intent service, String resolvedType,
            IServiceConnection connection, int flags, int userId) throws RemoteException;
    public boolean unbindService(IServiceConnection connection) throws RemoteException;
    public void publishService(IBinder token,
            Intent intent, IBinder service) throws RemoteException;
    …………………………
}
           

看到沒,是不是有很多方法我們都比較熟悉,并且我們還看到它繼承了IInterface接口,在我們平時實作跨程序IPC調用的時候是不是要繼承這個接口,是以我們基本可以判定ActivityManagerNative其實就是一個跨程序調用的類,并且ActivityManagerService是他的真正實作類,我們可以看一下

public final class ActivityManagerService extends ActivityManagerNative
        implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
           

他是個final類型,不能被繼承,我們來看它的startActivity方法

@Override
    public final int startActivity(IApplicationThread caller, String callingPackage,
            Intent intent, String resolvedType, IBinder resultTo,
            String resultWho, int requestCode, int startFlags,
            String profileFile, ParcelFileDescriptor profileFd, Bundle options) {
        return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,
                resultWho, requestCode,
                startFlags, profileFile, profileFd, options, UserHandle.getCallingUserId());
    }
           

繼續,我們來看一下startActivityAsUser的源碼

@Override
    public final int startActivityAsUser(IApplicationThread caller, String callingPackage,
            Intent intent, String resolvedType, IBinder resultTo,
            String resultWho, int requestCode, int startFlags,
            String profileFile, ParcelFileDescriptor profileFd, Bundle options, int userId) {
        enforceNotIsolatedCaller("startActivity");
        userId = handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(), userId,
                false, true, "startActivity", null);
        // TODO: Switch to user app stacks here.
        return mStackSupervisor.startActivityMayWait(caller, -1, callingPackage, intent, resolvedType,
                resultTo, resultWho, requestCode, startFlags, profileFile, profileFd,
                null, null, options, userId, null);
    }
           

我們找到mStackSupervisor對象,其實他就是ActivityStackSupervisor,也是個final類型,我們簡單看一下

我們找到他的startActivityMayWait方法,代碼也不少,我們找關鍵的看

final int startActivityMayWait(IApplicationThread caller, int callingUid,
            String callingPackage, Intent intent, String resolvedType, IBinder resultTo,
            String resultWho, int requestCode, int startFlags, String profileFile,
            ParcelFileDescriptor profileFd, WaitResult outResult, Configuration config,
            Bundle options, int userId, IActivityContainer iContainer) {
        	…………………………
            int res = startActivityLocked(caller, intent, resolvedType, aInfo, resultTo, resultWho,
                    requestCode, callingPid, callingUid, callingPackage, startFlags, options,
                    componentSpecified, null, container);
        	…………………………
            return res;
        }
    }
           

繼續,我們在找到startActivityLocked方法,他的代碼量更多,同樣,我們還是找關鍵的來看

final int startActivityLocked(IApplicationThread caller,
            Intent intent, String resolvedType, ActivityInfo aInfo, IBinder resultTo,
            String resultWho, int requestCode,
            int callingPid, int callingUid, String callingPackage, int startFlags, Bundle options,
            boolean componentSpecified, ActivityRecord[] outActivity, ActivityContainer container) {
        int err = ActivityManager.START_SUCCESS;
        …………………………
        err = startActivityUncheckedLocked(r, sourceRecord, startFlags, true, options);
        …………………………
        return err;
    }
           

我們繼續找到startActivityUncheckedLocked這個方法,代碼量是一個比一個長,沒關系,我們還是看關鍵部分

final int startActivityUncheckedLocked(ActivityRecord r,
            ActivityRecord sourceRecord, int startFlags, boolean doResume,
            Bundle options) {
    	…………………………
     
        } else if (sourceRecord.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
            launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
        } else if (r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE
                || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) {
            launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
        }
        …………………………
            ActivityRecord intentActivity = r.launchMode != ActivityInfo.LAUNCH_SINGLE_INSTANCE
                    ? findTaskLocked(r)
                    : findActivityLocked(intent, r.info);
            if (intentActivity != null) {
                if (r.task == null) {
                    r.task = intentActivity.task;
                }
                targetStack = intentActivity.task.stack;
                targetStack.mLastPausedActivity = null;
               …………………………
                if ((launchFlags&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
                    intentActivity = targetStack.resetTaskIfNeededLocked(intentActivity, r);
                }
                …………………………
                targetStack.resumeTopActivityLocked(null);
                …………………………

        return ActivityManager.START_SUCCESS;
    }
           

看到沒,這裡面有很多啟動模式,和我們設定的啟動模式是有關的,關于Android的4中啟動模式不作為我們這篇介紹的重點,我們來看一下上面倒數第二行代碼,我們找到targetStack這個對象,發現他其實就是ActivityStack,他也是final類型的,我們可以看一下

/**
 * State and management of a single stack of activities.
 */
final class ActivityStack {
           

我們找到resumeTopActivityLocked這個方法

final boolean resumeTopActivityLocked(ActivityRecord prev) {
        return resumeTopActivityLocked(prev, null);
    }
           

發現他被重構了,我們繼續檢視他的源碼,發現代碼量也多的吓死人,還是那樣,我們撿主要的看

final boolean resumeTopActivityLocked(ActivityRecord prev, Bundle options) {
    	…………………………
            mStackSupervisor.startSpecificActivityLocked(next, true, true);
    	…………………………
        return true;
    }
           

通過檢視源碼我們發現mStackSupervisor就是我們之前的ActivityStackSupervisor,就等于說我們繞了一圈又繞回來了,沒關系,那我們繼續檢視他的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, 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);
    }
           

我們主要來看一下try中的代碼塊,找到realStartActivityLocked的源碼,這個代碼量也不少,我們還是找主要的看

final boolean realStartActivityLocked(ActivityRecord r,
            ProcessRecord app, boolean andResume, boolean checkConfig)
            throws RemoteException {
    	…………………………
        mWindowManager.setAppVisibility(r.appToken, true);
        …………………………
            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) {}
        …………………………
        return true;
    }
           

看到沒,大家是不是有點興奮,我們知道上面的thread其實就是ActivityThread,在之前我們大緻說過在ActivityThread有個Main方法,裡面有一些looper及一些其他資料的初始化等,這個以後我們在介紹,我們先來看看scheduleLaunchActivity這個方法

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) {
        	…………………………
            sendMessage(H.LAUNCH_ACTIVITY, r);
        }
           

我們知道上面的H其實就是一個Handler,我們來看一下他的源碼,代碼量也比較多,我們就找我們需要的看

private class H extends Handler {
        public static final int LAUNCH_ACTIVITY         = 100;
        …………………………
        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");
                    ActivityClientRecord r = (ActivityClientRecord)msg.obj;

                    r.packageInfo = getPackageInfoNoCheck(
                            r.activityInfo.applicationInfo, r.compatInfo);
                    handleLaunchActivity(r, null);
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                } break;
               …………………………
            }
           

我們上面調用了handleLaunchActivity這個方法,接着我們在繼續找這個方法,随便檢視一下他的源碼

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);
            …………………………
                r.paused = true;
            }
        } else {
        	…………………………
        }
    }
           

我們看到performLaunchActivity傳回一個Activity,之前估計我們很多都不知道Activity究竟是怎麼初始化的,這回大家終于明白了吧,我們随便看一下他的源碼

private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
    	…………………………
        Activity activity = null;
        try {
            java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
            //建立Activity
            activity = mInstrumentation.newActivity(
                    cl, component.getClassName(), r.intent);
          …………………………

        try {
            //建立Application
        	Application app = r.packageInfo.makeApplication(false, mInstrumentation);
            …………………………
            if (activity != null) {
                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的attach方法,這個我們在前面講的時候也多次提及
                activity.attach(appContext, this, getInstrumentation(), r.token,
                        r.ident, app, r.intent, r.activityInfo, title, r.parent,
                        r.embeddedID, r.lastNonConfigurationInstances, config);

                …………………………
                int theme = r.activityInfo.getThemeResource();
                if (theme != 0) {
                   // 設定主題
                	activity.setTheme(theme);
                }

                //調用Activity的OnCreate方法,
                mInstrumentation.callActivityOnCreate(activity, r.state);
               …………………………
                if (!r.activity.mFinished) {
                    //調用Activity的onStart方法
                	activity.performStart();
                    r.stopped = false;
                }
                if (!r.activity.mFinished) {
                    if (r.state != null) {
                       //調用Activity的OnRestoreInstanceState方法
                    	mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state);
                    }
                }
               …………………………
        return activity;
    }
           

Activity是通過Instrumentation這個類建立的,我們可以看一下,代碼非常簡短

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

我們可以看到performLaunchActivity方法調用了Activity的onCreate方法和onStart方法,然後我們在看上面的handleLaunchActivity方法在調用完performLaunchActivity方法的時候又調用了handleResumeActivity方法。我們也可以順便看一下他的源碼

final void handleResumeActivity(IBinder token, boolean clearHide, boolean isForward,
            boolean reallyResume) {
    	…………………………
    	//調用了Activity的performResume方法,然後執行onResume方法
        ActivityClientRecord r = performResumeActivity(token, clearHide);

        if (r != null) {
            final Activity a = r.activity;
            …………………………
            boolean willBeVisible = !a.mStartedActivity;
            …………………………
            if (r.window == null && !a.mFinished && willBeVisible) {
                r.window = r.activity.getWindow();
                View decor = r.window.getDecorView();
                decor.setVisibility(View.INVISIBLE);
                ViewManager wm = a.getWindowManager();
                WindowManager.LayoutParams l = r.window.getAttributes();
                a.mDecor = decor;
                l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
                l.softInputMode |= forwardBit;
                if (a.mVisibleFromClient) {
                    a.mWindowAdded = true;
                    wm.addView(decor, l);
                }
                …………………………
                r.activity.mVisibleFromServer = true;
                mNumVisibleActivities++;
                if (r.activity.mVisibleFromClient) {
                    //調用Activity的makeVisible方法
                	r.activity.makeVisible();
                }
            }
            …………………………
    }
           

經過上面一步步的分析,Activity的onCreat方法,onStart方法和onResume方法就全部都已經啟動,一個全新的Activity就展現在我們面前,OK,到目前為止startActivity的方法就全部已經分析完畢