Android插件化架構(gòu) - Activity的啟動流程分析

1. 概述


Android插件化架構(gòu)穆碎,目前第三方的框架比較多,早幾年自己用的是DL框架职恳,這個框架的源碼比較簡單主要用的是靜態(tài)代理所禀。如果我們自己要去寫一個插件化架構(gòu)框架那要解決的問題會分為幾個方面,類的加載放钦,資源和布局的加載色徘,廣播的管理方式,Activity的加載和生命周期管理操禀,Service的插件化褂策,ContentProvider的插件化等等等等,反正加載一個沒有運(yùn)行的app到主程序颓屑,需要解決的問題基本就這么多斤寂,如果能夠一一解決那么就可以實(shí)現(xiàn)插件化了。
  內(nèi)涵段子項(xiàng)目部分我們實(shí)現(xiàn)幾個揪惦,然后介紹一個360開源框架DroidPlugin原理一致遍搞,后面我們再一一實(shí)現(xiàn),那么這一期實(shí)現(xiàn)什么呢丹擎?我們需要啟動插件APP那么就需要啟動里面的Activity,這些Activity事先是不會在主工程的AndroidManifest.xml中配置尾抑,啟動一個沒有注冊的Activity肯定會報錯,我們是否可以想個辦法去繞過系統(tǒng)的檢測蒂培,讓沒有在AndroidManifest.xml中配置的Activity照樣可以啟動呢再愈?
  看源碼的時候我們其實(shí)時常強(qiáng)調(diào)一定要帶著思想,要解決這么個問題我們肯定需要清楚的知道系統(tǒng)啟動Activity的具體流程护戳,當(dāng)然可以直接去了解為什么報錯翎冲,這里我們還是把啟動流程全部走一遍,也方便以后開發(fā)中再遇到什么問題媳荒。

2. Activity啟動流程源碼分析

     
    @Override
    public void startActivity(Intent intent, @Nullable 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(@RequiresPermission Intent intent, int requestCode,
            @Nullable Bundle options) {
        if (mParent == null) {
            options = transferSpringboardActivityOptions(options);
            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;
            }

            cancelInputsAndStartExitTransition(options);
            // 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);
            }
        }
    }

來到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);
        }
        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(who);
            int result = ActivityManagerNative.getDefault()
                .startActivity(whoThread, who.getBasePackageName(), intent,
                        intent.resolveTypeIfNeeded(who.getContentResolver()),
                        token, target != null ? target.mEmbeddedID : null,
                        requestCode, 0, null, options);
            checkStartActivityResult(result, intent);
        } catch (RemoteException e) {
            throw new RuntimeException("Failure from system", e);
        }
        return null;
    }
    
    // 檢測結(jié)果也就是否正常
    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:
                // 在這里就會報各種錯抗悍,AndroidManifest.xml中沒有配置的錯就出現(xiàn)在這
                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);
        }
    }


ActivityManagerNative.getDefault().startActivity又是一個進(jìn)程間的通信驹饺,如果不了解IPC的請移步Android進(jìn)程間的通信 - IPC(機(jī)制)Binder的原理和源碼閱讀,來到ActivityManagerService中的startActivity方法:

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

    final int startActivityMayWait(IApplicationThread caller, int callingUid,
            String callingPackage, Intent intent, String resolvedType,
            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
            IBinder resultTo, String resultWho, int requestCode, int startFlags,
            ProfilerInfo profilerInfo, IActivityManager.WaitResult outResult, Configuration config,
            Bundle bOptions, boolean ignoreTargetSecurity, int userId,
            IActivityContainer iContainer, TaskRecord inTask) {
            
            // PackageManagerService-----> 掃描app缴渊,注冊組件

            ResolveInfo rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId);
            // Collect information about the target of the Intent.
            ActivityInfo aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, profilerInfo);

            rInfo = mSupervisor.resolveIntent(intent, null /*resolvedType*/, userId);

            int res = startActivityLocked(caller, intent, ephemeralIntent, resolvedType,
                    aInfo, rInfo, voiceSession, voiceInteractor,
                    resultTo, resultWho, requestCode, callingPid,
                    callingUid, callingPackage, realCallingPid, realCallingUid, startFlags,
                    options, ignoreTargetSecurity, componentSpecified, outRecord, container,
                    inTask);
     }

     final int startActivityLocked(IApplicationThread caller, Intent intent, Intent ephemeralIntent,
            String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo,
            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
            IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid,
            String callingPackage, int realCallingPid, int realCallingUid, int startFlags,
            ActivityOptions options, boolean ignoreTargetSecurity, boolean componentSpecified,
            ActivityRecord[] outActivity, ActivityStackSupervisor.ActivityContainer container,
            TaskRecord inTask) {
            
            // 驗(yàn)證intent赏壹、Class、Permission等
            // 保存將要啟動的Activity的Record
            err = startActivityUnchecked(r, sourceRecord, voiceSession, voiceInteractor, startFlags,
                    true, options, inTask);
            return err;
      }

      private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
            int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask) {
            // 檢查將要啟動的Activity的launchMode和啟動Flag
            // 根據(jù)launcheMode和Flag配置task
            final boolean dontStart = top != null && mStartActivity.resultTo == null
                && top.realActivity.equals(mStartActivity.realActivity)
                && top.userId == mStartActivity.userId
                && top.app != null && top.app.thread != null
                && ((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0
                || mLaunchSingleTop || mLaunchSingleTask);
            // 舉一個例子 SingleTop
            if (dontStart) {
                top.deliverNewIntentLocked(
                    mCallingUid, mStartActivity.intent, mStartActivity.launchedFromPackage);

               // Don't use mStartActivity.task to show the toast. We're not starting a new activity
               // but reusing 'top'. Fields in mStartActivity may not be fully initialized.
               mSupervisor.handleNonResizableTaskIfNeeded(
                    top.task, preferredLaunchStackId, topStack.mStackId);
           
               return START_DELIVERED_TO_TOP;
            }

            mTargetStack.startActivityLocked(mStartActivity, newTask, mKeepCurTransition, mOptions);
            if (mDoResume) {
                  mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity,
                        mOptions);
            }
      }

進(jìn)入ActvityStack中的startActivityLocked()方法

      // 任務(wù)棧歷史棧配置
      final void startActivityLocked(ActivityRecord r, boolean newTask, boolean keepCurTransition,
            ActivityOptions options) {
            if (!r.mLaunchTaskBehind && (taskForIdLocked(taskId) == null || newTask)) {
                // 加入棧頂 管理?xiàng)?                insertTaskAtTop(rTask, r);
                // 管顯示
                mWindowManager.moveTaskToTop(taskId);
            }
          
            if (!newTask) {
                // 不是一個新的Task
                task.addActivityToTop(r);
                r.putInHistory();
                addConfigOverride(r, task);
            }
      }

進(jìn)入ActivityStack的resumeTopActivityInnerLocked()方法

      private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {
           // Find the first activity that is not finishing.
           final ActivityRecord next = topRunningActivityLocked();
            
           // The activity may be waiting for stop, but that is no longer
           // appropriate for it.
           mStackSupervisor.mStoppingActivities.remove(next);
           mStackSupervisor.mGoingToSleepActivities.remove(next);
           next.sleeping = false;
           mStackSupervisor.mWaitingVisibleActivities.remove(next);

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

      final boolean startPausingLocked(boolean userLeaving, boolean uiSleeping,
            ActivityRecord resuming, boolean dontWait) {
            
            if (prev.app != null && prev.app.thread != null) {
            if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Enqueueing pending pause: " + prev);
            try {
                EventLog.writeEvent(EventLogTags.AM_PAUSE_ACTIVITY,
                        prev.userId, System.identityHashCode(prev),
                        prev.shortComponentName);
                mService.updateUsageStats(prev, false);
                // 暫停Activity
                prev.app.thread.schedulePauseActivity(prev.appToken, prev.finishing,
                        userLeaving, prev.configChangeFlags, dontWait);
            }

            completePauseLocked(false, resuming);
      }

進(jìn)入ApplicationThread的schedulePauseActivity()方法

      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 ? USER_LEAVING : 0) | (dontReport ? DONT_REPORT : 0),
                    configChanges,
                    seq);
      }

      public void handleMessage(Message msg) {
            switch (msg.what) {
                ...
            case PAUSE_ACTIVITY: {
                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityPause");
                    SomeArgs args = (SomeArgs) msg.obj;
                    handlePauseActivity((IBinder) args.arg1, false,
                            (args.argi1 & USER_LEAVING) != 0, args.argi2,
                            (args.argi1 & DONT_REPORT) != 0, args.argi3);
                    maybeSnapshot();
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
           } break;
       }

       private void handlePauseActivity(IBinder token, boolean finished,
            boolean userLeaving, int configChanges, boolean dontReport, int seq) {
            //... 
            performPauseActivity(token, finished, r.isPreHoneycomb(), "handlePauseActivity");
            //...
            // Tell the activity manager we have paused.
            if (!dontReport) {
                try {
                    ActivityManagerNative.getDefault().activityPaused(token);
                } catch (RemoteException ex) {
                    throw ex.rethrowFromSystemServer();
                }
            }
       }

       final Bundle performPauseActivity(IBinder token, boolean finished,
            boolean saveState, String reason) {
            ActivityClientRecord r = mActivities.get(token);
            return r != null ? performPauseActivity(r, finished, saveState, reason) : null;
       }

       final Bundle performPauseActivity(ActivityClientRecord r, boolean finished,
            boolean saveState, String reason) {
            // ...
            performPauseActivityIfNeeded(r, reason);
       }

       private void performPauseActivityIfNeeded(ActivityClientRecord r, String reason) {
            // ...
            mInstrumentation.callActivityOnPause(r.activity);
       }

進(jìn)入Instrumentation的callActivityOnPause()方法

    public void callActivityOnPause(Activity activity) {
        activity.performPause();
    }

進(jìn)入Activity的performPause()方法

final void performPause() {
        mDoReportFullyDrawn = false;
        mFragments.dispatchPause();
        mCalled = false;
        // 調(diào)用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;
    }

總算是回調(diào)到了Activity的onPause方法衔沼,哈哈還是挺簡單的蝌借,Activity生命周期中的onPause方法終于被我們找到了。也就是說我們在啟動一個Activity的時候最先被執(zhí)行的是棧頂?shù)腁ctivity的onPause方法指蚁。我們對Activity這些生命周期早已背得滾瓜爛熟菩佑。接著往下看然后回到我們ApplicationThread的handlePauseActivity()方法中的ActivityManagerNative.getDefault().activityPaused(token);進(jìn)入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);
     }

進(jìn)入ActivityStack中的activityPausedLocked()方法

    final void activityPausedLocked(IBinder token, boolean timeout){
        completePauseLocked(true, null);
    }
    private void completePauseLocked(boolean resumeNext, ActivityRecord resuming) {
        ActivityRecord prev = mPausingActivity;
        if (resumeNext) {
            final ActivityStack topStack = mStackSupervisor.getFocusedStack();
            mStackSupervisor.resumeFocusedStackTopActivityLocked(topStack, prev, null);
        }
    }

進(jìn)入ActivityStackSupervisor中的resumeFocusedStackTopActivityLocked()方法

    boolean resumeFocusedStackTopActivityLocked(
        ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) {
        targetStack.resumeTopActivityUncheckedLocked(target, targetOptions);
    }

進(jìn)入ActivityStack中的resumeTopActivityUncheckedLocked()方法

    boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options) {
        result = resumeTopActivityInnerLocked(prev, options);
    }

    private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {
        // 這個方法我們已經(jīng)很熟悉了
        mStackSupervisor.startSpecificActivityLocked(next, true, true);
    }

進(jìn)入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, r.info.applicationInfo.versionCode,
                            mService.mProcessStats);
                }
                // 真的要啟動Activity了
                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);
    }

    final boolean realStartActivityLocked(ActivityRecord r, ProcessRecord app,
            boolean andResume, boolean checkConfig) throws RemoteException {
            // scheduleLaunchActivity 啟動
            app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
                    System.identityHashCode(r), r.info, new Configuration(mService.mConfiguration),
                    new Configuration(task.mOverrideConfig), r.compat, r.launchedFromPackage,
                    task.voiceInteractor, app.repProcState, r.icicle, r.persistentState, results,
                    newIntents, !andResume, mService.isNextTransitionForward(), profilerInfo);
    }

進(jìn)入ApplicationThread中的scheduleLaunchActivity()方法

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


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

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

        Activity a = performLaunchActivity(r, customIntent);

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

            if (!r.activity.mFinished && r.startsNotResumed) {
                // The activity manager actually wants this one to start out paused, because it
                // needs to be visible but isn't in the foreground. We accomplish this by going
                // through the normal startup (because activities expect to go through onResume()
                // the first time they run, before their window is displayed), and then pausing it.
                // However, in this case we do -not- need to do the full pause cycle (of freezing
                // and such) because the activity manager assumes it can just retain the current
                // state it has.
                performPauseActivityIfNeeded(r, reason);

                // We need to keep around the original state, in case we need to be created again.
                // But we only do this for pre-Honeycomb apps, which always save their state when
                // pausing, so we can not have them save their state when restarting from a paused
                // state. For HC and later, we want to (and can) let the state be saved as the
                // normal part of stopping the activity.
                if (r.isPreHoneycomb()) {
                    r.state = oldState;
                }
            }
        } else {
            // If there was an error, for any reason, tell the activity manager to stop us.
            try {
                ActivityManagerNative.getDefault()
                    .finishActivity(r.token, Activity.RESULT_CANCELED, null,
                            Activity.DONT_FINISH_TASK_WITH_ACTIVITY);
            } catch (RemoteException ex) {
                throw ex.rethrowFromSystemServer();
            }
        }
    }

3. Activity啟動流程總結(jié)


剛開始去看估計要看個一兩天才會有所收貨,其實(shí)看源碼要么是為了解決問題要么是為了學(xué)習(xí)凝化,否則還是不要輕易的進(jìn)入這趟渾水里面稍坯,代碼太多了沒有思想會蒙的。首先可以大致先走一遍流程搓劫,然后再去抓細(xì)節(jié)瞧哟,比如怎么分配棧的,怎么處理啟動模式的糟把,怎么創(chuàng)建Activity的绢涡,怎么調(diào)用生命周期的,怎么傳遞序列化對象參數(shù)的等等......
  看了源碼之后我們不得不佩服Google的工程師遣疯,寫的代碼可擴(kuò)展真的很不錯雄可,要是換做一般人版本迭代幾次代碼就改不動了,得要重新架構(gòu)重新寫缠犀,這也是我們學(xué)習(xí)的方式数苫,源碼其實(shí)是最好的書籍。這里有好幾個思想辨液,C/S架構(gòu)思想就是服務(wù)思想虐急,模塊化思想,分層次思想等等...

最后我們看一下在啟動流程中出現(xiàn)的幾個主要的類都分別有什么功能:

  • ** ActivityManagerService** 組件通信系統(tǒng)核心管理類 (ActivityManagerNative)IPC通信
  • ** ActivityStackSupervisor** 管理整個手機(jī)的Activity任務(wù)棧
  • ActivityStack Activity棧(任務(wù)棧)
  • ** PackageManagerService** 主要負(fù)責(zé)對系統(tǒng)的apk進(jìn)行管理滔迈,不管是系統(tǒng)apk(/system/app)止吁,還是我們手工安裝上去的,系統(tǒng)所有的apk都是由其管理的燎悍。
  • ** ActivityThread** Activity的入口是onCreate方法敬惦,Android上一個應(yīng)用的入口是ActivityThread。和普通的Java類一樣有一個main方法谈山。用于控制與管理一個應(yīng)用進(jìn)程的主線程的操作俄删,包括管理與處理activity manager發(fā)送過來的關(guān)于activities、廣播以及其他的操作請求

ActivityManagerService和ActivityStack位于同一個進(jìn)程中,而ApplicationThread和ActivityThread位于另一個進(jìn)程中畴椰。其中臊诊,ActivityManagerService是負(fù)責(zé)管理Activity的生命周期的,ActivityManagerService還借助ActivityStack是來把所有的Activity按照后進(jìn)先出的順序放在一個堆棧中斜脂;對于每一個應(yīng)用程序來說抓艳,都有一個ActivityThread來表示應(yīng)用程序的主進(jìn)程,而每一個ActivityThread都包含有一個ApplicationThread實(shí)例秽褒,它是一個Binder對象壶硅,負(fù)責(zé)和其它進(jìn)程進(jìn)行通信。

這么痛苦的去讀源碼到底有什么用呢销斟?那么結(jié)合動態(tài)代碼設(shè)計模式以及Activity的啟動流程,我們就可以嘗試去攔截Activity的啟動流程椒舵,讓沒有在AndroidMainfest.xml中注冊的Activity也能啟動并且不報錯蚂踊,這樣我們就算是跨出了插件化架構(gòu)的第一步了,如果你不去了解Activity啟動流程那么就是然并卵笔宿。

所有分享大綱:2017Android進(jìn)階之路與你同行

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末犁钟,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子泼橘,更是在濱河造成了極大的恐慌涝动,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,941評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件炬灭,死亡現(xiàn)場離奇詭異醋粟,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)重归,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,397評論 3 395
  • 文/潘曉璐 我一進(jìn)店門米愿,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人鼻吮,你說我怎么就攤上這事育苟。” “怎么了椎木?”我有些...
    開封第一講書人閱讀 165,345評論 0 356
  • 文/不壞的土叔 我叫張陵违柏,是天一觀的道長。 經(jīng)常有香客問我香椎,道長漱竖,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,851評論 1 295
  • 正文 為了忘掉前任士鸥,我火速辦了婚禮闲孤,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己讼积,他們只是感情好肥照,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,868評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著勤众,像睡著了一般舆绎。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上们颜,一...
    開封第一講書人閱讀 51,688評論 1 305
  • 那天吕朵,我揣著相機(jī)與錄音,去河邊找鬼窥突。 笑死努溃,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的阻问。 我是一名探鬼主播梧税,決...
    沈念sama閱讀 40,414評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼称近!你這毒婦竟也來了第队?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,319評論 0 276
  • 序言:老撾萬榮一對情侶失蹤刨秆,失蹤者是張志新(化名)和其女友劉穎凳谦,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體衡未,經(jīng)...
    沈念sama閱讀 45,775評論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡尸执,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了眠屎。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片剔交。...
    茶點(diǎn)故事閱讀 40,096評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖改衩,靈堂內(nèi)的尸體忽然破棺而出岖常,到底是詐尸還是另有隱情,我是刑警寧澤葫督,帶...
    沈念sama閱讀 35,789評論 5 346
  • 正文 年R本政府宣布竭鞍,位于F島的核電站,受9級特大地震影響橄镜,放射性物質(zhì)發(fā)生泄漏偎快。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,437評論 3 331
  • 文/蒙蒙 一洽胶、第九天 我趴在偏房一處隱蔽的房頂上張望晒夹。 院中可真熱鬧,春花似錦、人聲如沸丐怯。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,993評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽读跷。三九已至梗搅,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間效览,已是汗流浹背无切。 一陣腳步聲響...
    開封第一講書人閱讀 33,107評論 1 271
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留丐枉,地道東北人哆键。 一個月前我還...
    沈念sama閱讀 48,308評論 3 372
  • 正文 我出身青樓,卻偏偏與公主長得像瘦锹,于是被迫代替她去往敵國和親洼哎。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,037評論 2 355

推薦閱讀更多精彩內(nèi)容