国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 系統 > Android > 正文

分析Android Activity的啟動過程

2019-10-22 18:32:44
字體:
來源:轉載
供稿:網友

分析Android Activity的啟動過程

          對于Android Activity 的啟動過程,我在Android源碼中讀了好久的源碼,以下是我整理出來的Activity啟動過程和大家分享下:

Activity作為Android的四大組件之一,也是最基本的組件,負責與用戶交互的所有功能。Activity的啟動過程也并非一件神秘的事情,接下來就簡單的從源碼的角度分析一下Activity的啟動過程。

根Activity一般就是指我們項目中的MainActivity,代表了一個android應用程序,一般也是在一個新的進程中啟動起來。在Android系統中,所有的Activity組件都保存在堆棧中,我們啟動一個新的Activity組件就位于上一個Activity的上面。那么我們從桌面(Launcher)打開一個App是一個怎樣的過程呢,如下所示:

    (1)Launcher向ActivityManagerService發送一個啟動MainActivity的請求;
    (2)ActivityManagerService首先將MainActivity的相關信息保存下來,然后向Launcher發送一個使之進入中止狀態的請求;
    (3)Launcher收到中止狀態之后,就會想ActivityManagerService發送一個已進入中止狀態的請求,便于ActivityManagerService繼續執行啟動MainActivity的操作;
    (4)ActivityManagerService檢查用于運行MainActivity的進程,如果不存在,則啟動一個新的進程;
    (5)新的應用程序進程啟動完成之后,就會向ActivityManagerService發送一個啟動完成的請求,便于ActivityManagerService繼續執行啟動MainActivity的操作;
    (6)ActivityManagerService將第(2)步保存下來的MainActivity相關信息發送給新創建的進程,便于該進程啟動MainActivity組件。

Launcher.startActivitySafely

boolean startActivitySafely(Intent intent, Object tag) {   intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);   try {    startActivity(intent);    return true;   } catch (ActivityNotFoundException e) {} } 

當我們在Launcher上點擊應用程序圖標時,startActivitySafely方法會被調用。需要啟動的Activity信息保存在intent中,包括action、category等等。那么Launcher是如何獲得intent里面的這些信息呢?首先,系統在啟動時會啟動一個叫做PackageManagerService的管理服務,并且通過他來安裝系統中的應用程序,在這個過程中,PackageManagerService會對應用程序的配置文件AndroidManifest.xml進行解析,從而得到程序里的組件信息(包括Activity、Service、Broadcast等),然后PackageManagerService去查詢所有action為“android.intent.action.MAIN”并且category為“android.intent.category.LAUNCHER”的Activity,然后為每個應用程序創建一個快捷方式圖標,并把程序信息與之關聯。上述代碼中,Activity的啟動標志位設置為“Intent.FLAG_ACTIVITY_NEW_TASK”,便于他可以在一個新的任務中啟動。

Activity.startActivity

@Override  public void startActivity(Intent intent, @Nullable Bundle options) {   if (options != null) {    startActivityForResult(intent, -1, options);   } else {    startActivityForResult(intent, -1);   }  } 

調用startActivityForResult,第二個參數(requestCode)為-1則表示在Activity關閉時不需要將結果傳回來。

Activity.startActivityForResult

public void startActivityForResult(Intent intent, int requestCode, @Nullable Bundle options) {   if (mParent == null) { //一般的Activity其mParent都為null    Instrumentation.ActivityResult ar = mInstrumentation.execStartActivity(this,       mMainThread.getApplicationThread(), mToken, this,intent, requestCode, options);    if (ar != null) { //發送結果,即onActivityResult會被調用     mMainThread.sendActivityResult(mToken, mEmbeddedID, requestCode, ar.getResultCode(),       ar.getResultData());    }    if (requestCode >= 0) {     mStartedActivity = true;    }     final View decor = mWindow != null ? mWindow.peekDecorView() : null;    if (decor != null) {     decor.cancelPendingInputEvents();    }   } else { //在ActivityGroup內部的Activity,內部處理邏輯和上面是類似的    if (options != null) {     mParent.startActivityFromChild(this, intent, requestCode, options);    } else {     mParent.startActivityFromChild(this, intent, requestCode);    }   }   if (options != null && !isTopOfTask()) {    mActivityTransitionState.startExitOutTransition(this, options);   }  } 

不難發現,最后實際上是調用mInstrumentation.execStartActivity來啟動Activity,mInstrumentation類型為Instrumentation,用于監控程序和系統之間的交互操作。mInstrumentation代為執行Activity的啟動操作,便于他可以監控這一個交互過程。

mMainThread的類型為ActivityThread,用于描述一個應用程序進程,系統每啟動一個程序都會在它里面加載一個ActivityThread的實例,并且將該實例保存在Activity的成員變量mMainThread中,而mMainThread.getApplicationThread()則用于獲取其內部一個類型為ApplicationThread的本地Binder對象。mToken的類型為IBinder,他是一個Binder的代理對象,只想了ActivityManagerService中一個類型為ActivityRecord的本地Binder對象。每一個已經啟動的Activity在ActivityManagerService中都有一個對應的ActivityRecord對象,用于維護Activity的運行狀態及信息。

Instrumentation.execStartActivity

public ActivityResult execStartActivity(Context who, IBinder contextThread, IBinder token, Activity 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++) { //先查找一遍看是否存在這個activity      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.mEmbeddedID : null,       requestCode, 0, null, options); //這里才是真正打開activity的地方,其核心功能在whoThread中完成。    checkStartActivityResult(result, intent); // 處理各種異常,如ActivityNotFound   } catch (RemoteException e) {   }   return null;  } 

上述代碼可知,通過ActivityManagerNative.getDefault()獲取一個ActivityManagerService的代理對象,然后調用他的startActivity方法來通知ActivityManagerService去啟動Activity。

中間還有一系列過程,跟著源碼走下去,不難發現,最后,是調用ApplicationThread的scheduleLaunchActivity來進行Activity的啟動。

Application.scheduleLaunchActivity

public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,     ActivityInfo info, Configuration curConfig, 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;     updatePendingConfiguration(curConfig);     sendMessage(H.LAUNCH_ACTIVITY, r);   } 

上述代碼主要做的事就是構造一個ActivityClientRecord,然后調用sendMessage發送一個消息。在應用程序對應的進程中,每一個Activity組件都使用一個ActivityClientRecord對象來描述,他們保存在ActivityThread類的成員變量mActivities中。那么Handler是如何處理這個消息的呢?

H.handleMessage

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); // 處理消息    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);   } break;   case RELAUNCH_ACTIVITY: {    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityRestart");    ActivityClientRecord r = (ActivityClientRecord)msg.obj;    handleRelaunchActivity(r);    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);   } break;   case PAUSE_ACTIVITY:    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityPause");    handlePauseActivity((IBinder)msg.obj, false, (msg.arg1&1) != 0, msg.arg2,      (msg.arg1&2) != 0);    maybeSnapshot();    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);    break;   ... ... } 

首先將msg里面的obj轉成一個ActivityClientRecord對象,然后調用來獲取一個LoaderApk對象并保存在ActivityClientRecord對象的成員變量packageInfo中。Loader對象用于描述一個已經加載的APK文件。最后調用handleLaunchActivity來啟動Activity組件。

ActivityThread.handleLaunchActivity

private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent) {   unscheduleGcIdler();   mSomeActivitiesChanged = true;    if (r.profilerInfo != null) {    mProfiler.setProfiler(r.profilerInfo);    mProfiler.startProfiling();   }    handleConfigurationChanged(null, null);    if (localLOGV) Slog.v(    TAG, "Handling launch of " + r);    WindowManagerGlobal.initialize();    Activity a = performLaunchActivity(r, customIntent); //performLaunchActivity真正完成了activity的調起,Activity被實例化,onCreate被調用    if (a != null) {    r.createdConfig = new Configuration(mConfiguration);    Bundle oldState = r.state;    handleResumeActivity(r.token, false, r.isForward, // 再調用Activity實例的Resume(用戶界面可見)      !r.activity.mFinished && !r.startsNotResumed);     if (!r.activity.mFinished && r.startsNotResumed) {     try {      r.activity.mCalled = false;      mInstrumentation.callActivityOnPause(r.activity); // finish的時候先調onPause      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) {      if (!mInstrumentation.onException(r.activity, e)) {       throw new RuntimeException(         "Unable to pause activity "         + r.intent.getComponent().toShortString()         + ": " + e.toString(), e);      }     }     r.paused = true;    }   } else {    try {     ActivityManagerNative.getDefault() // finishActivity 一樣的原理      .finishActivity(r.token, Activity.RESULT_CANCELED, null, false);    } catch (RemoteException ex) {    }   }  } 

到了這一步,那就很清晰了。憋了一口氣到這里,是不是突然放松了一下~~  再來看看performLaunchActivity做的事兒~~performLaunchActivity函數加載用戶自定義的Activity的派生類,并執行其onCreate函數,它將返回此Activity對象。

ActivityThread.performLaunchActivity

private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {   ActivityInfo aInfo = r.activityInfo;   if (r.packageInfo == null) {    r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo,      Context.CONTEXT_INCLUDE_CODE);   }   //從intent中取出目標activity的啟動參數(包名、類名等)   ComponentName component = r.intent.getComponent();   if (component == null) {    component = r.intent.resolveActivity(     mInitialApplication.getPackageManager());    r.intent.setComponent(component);   }    if (r.activityInfo.targetActivity != null) {    component = new ComponentName(r.activityInfo.packageName,      r.activityInfo.targetActivity);   }    Activity activity = null;   try {    java.lang.ClassLoader cl = r.packageInfo.getClassLoader(); // 將Activity類文件加載到內存中    activity = mInstrumentation.newActivity( // 創建Activity實例      cl, component.getClassName(), r.intent);    StrictMode.incrementExpectedActivityCount(activity.getClass());    r.intent.setExtrasClassLoader(cl);    r.intent.prepareToEnterProcess();    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) {     Context appContext = createBaseContextForActivity(r, activity); // 初始化Context對象,作為Activity的上下文     CharSequence    Configuration config = new Configuration(mCompatConfiguration);     if (DEBUG_CONFIGURATION) Slog.v(TAG, "Launching activity "       + r.activityInfo.name + " with config " + config);     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);      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;     if (r.isPersistable()) { //下面就是調用到acitivity的onCreate方法了      mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);     } else {      mInstrumentation.callActivityOnCreate(activity, r.state);     } // 至此,Activity啟動過程就結束了,其生命周期由ApplicationThread來管理     if (!activity.mCalled) {      throw new SuperNotCalledException(       "Activity " + r.intent.getComponent().toShortString() +       " did not call through to super.onCreate()");     }     r.activity = activity;     r.stopped = true;     if (!r.activity.mFinished) {      activity.performStart();      r.stopped = false;     }     if (!r.activity.mFinished) {      if (r.isPersistable()) {       if (r.state != null || r.persistentState != null) {        mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state,          r.persistentState);       }      } else if (r.state != null) {       mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state);      }     }     if (!r.activity.mFinished) {      activity.mCalled = false;      if (r.isPersistable()) {       mInstrumentation.callActivityOnPostCreate(activity, r.state,         r.persistentState);      } else {       mInstrumentation.callActivityOnPostCreate(activity, r.state);      }      if (!activity.mCalled) {       throw new SuperNotCalledException(        "Activity " + r.intent.getComponent().toShortString() +        " did not call through to super.onPostCreate()");      }     }    }    r.paused = true;    mActivities.put(r.token, r); // 將ActivityRecord對象保存在ActivityThread的mActivities中   } 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;  } 

ActivityRecord里面的token,是一個Binder的代理對象,和ActivityClientRecord對象一樣,都是用來描述所啟動的Activity組件,只不過前者是在ActivityManagerService中使用,后者是在應用程序進程中使用。

至此,Activity的啟動過程就分析完了。MainActivity的啟動過程,其實也可以認為是應用程序的啟動過程。
子Activity的啟動過程和根Activity的啟動過程也是類似的,過程如下:

    (1)MainActivity向ActivityManagerService發送一個自動ChildActivity的請求;

    (2)ActivityManagerService首先將ChildActivity的信息保存下來,再向MainActivity發送一個中止的請求;

    (3)MainActivity收到請求進入中止狀態,告訴ActivityManagerService,便于ActivityManagerService繼續執行啟動ChildActivity的操作

    (4)ActivityManagerService檢查ChildActivity所運行的進程是否存在,存在就發送ChildActivity信息給他,以進行啟動。
源代碼方面,原理類似,相比起來會比MainActivity的稍微簡單一些,這里就不再詳細敘述了,各位可以自行根據前面步驟,閱讀源代碼。

感謝閱讀,希望能幫助到大家,謝謝大家對本站的支持!


注:相關教程知識閱讀請移步到Android開發頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 临城县| 黄平县| 汤阴县| 浦城县| 衡东县| 桃园市| 泰州市| 遵义市| 泾源县| 云梦县| 儋州市| 团风县| 桐城市| 木里| 崇州市| 宝坻区| 安乡县| 台北县| 萨嘎县| 景谷| 海原县| 咸丰县| 阜城县| 运城市| 台前县| 云林县| 扎囊县| 天门市| 桦南县| 江油市| 西峡县| 仁化县| 安丘市| 巴彦县| 郴州市| 盐津县| 麻城市| 自贡市| 宜兰市| 福建省| 巴中市|