欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

詳解Android Activity的啟動流程

 更新時間:2021年03月18日 10:24:56   作者:一碗清湯面  
這篇文章主要介紹了詳解Android Activity的啟動流程,幫助大家更好的理解和學習使用Android,感興趣的朋友可以了解下

前言

activity啟動的流程分為兩部分:一是在activity中通過startActivity(Intent intent)方法啟動一個Activity;二是我們在桌面通過點擊應用圖標啟動一個App然后顯示Activity;第二種方式相較于第一種方式更加全面,所以本文會以第二種流程來分析。

簡要

我們手機的桌面是一個叫做Launcher的Activity,它羅列了手機中的應用圖標,圖標中包含安裝apk時解析的應用默認啟動頁等信息。在點擊應用圖標時,即將要啟動的App和Launcher、AMS、Zygote所屬進程不同所以涉及到Launcher與AMS,AMS與Zygote,AMS與新App這四者多次通信,才會啟動一個App,然后再啟動Activity,整體的時序圖如下:

接下來根據源碼來梳理一下流程。

1.Launcher向AMS發(fā)送啟動Activity

Launcher本身是一個Activity,在用戶點擊應用圖標時,調用startActivitySafely方法,最后調用到Activity.startActivity(),函數調用如下

Launcher.java
 public boolean startActivitySafely(View v, Intent intent, ItemInfo item) {
  ...
  //標記在新的棧啟動
  intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
  ...
  startActivity(intent, optsBundle);
  ...
 }

Activity.java
 @Override
 public void startActivity(Intent intent) {
  this.startActivity(intent, null);
 }

 @Override
 public void startActivity(Intent intent, @Nullable Bundle options) {
  ...
  if (options != null) {
   //-1為requestCode表明不需要知道是否啟動成功
   startActivityForResult(intent, -1, options);
  } else {
   startActivityForResult(intent, -1);
  }
 }

 public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,
   @Nullable Bundle options) {
   ...
   Instrumentation.ActivityResult ar =
    mInstrumentation.execStartActivity(
     this, mMainThread.getApplicationThread(), mToken,this,intent, requestCode, options);
   ...
 }

每個Activity都持有Instrumentation對象,通過它的execStartActivity函數來繼續(xù)完成啟動Activity的流程,這個函數中傳入了mMainThread.getApplicationThread(),它獲取到的是ActivityThread的內部類ApplicationThread,這是一個Binder對象,之后AMS通過此對象與App的通信。

Instrumentation.java
public ActivityResult execStartActivity(
   Context who, IBinder contextThread, IBinder token, Activity target,
   Intent intent, int requestCode, Bundle options) {
 ...
	int result = ActivityTaskManager.getService().startActivity(whoThread,who.getBasePackageName(),
  who.getAttributionTag(),intent,intent.resolveTypeIfNeeded(who.getContentResolver()),
  token,target != null ? target.mEmbeddedID : null, requestCode, 0, null, options); 
 ...
}

ActivityTaskManager.java
public static IActivityTaskManager getService() {
  return IActivityTaskManagerSingleton.get();
}
 
private static final Singleton<IActivityTaskManager> IActivityTaskManagerSingleton =
   new Singleton<IActivityTaskManager>() {
    @Override
    protected IActivityTaskManager create() {
     final IBinder b = ServiceManager.getService(Context.ACTIVITY_TASK_SERVICE);
     return IActivityTaskManager.Stub.asInterface(b);
    }
    }
};

這一步Launcher開始向AMS通信,由于在不同的進程所以需要通過Binder來通信,IActivityTaskManager是一個代理AMS端Binder的對象,之后AMS開始startActivity。 到這里Launcher向AMS請求啟動一個Activity的流程就結束了。

2.AMS啟動Activity并通知Launcher進入Paused狀態(tài)

現在的流程是在AMS中,也就是另一個進程中,上一步通過代理調用到AMS的startActivity方法,接下來的調用如下:

ActivityTaskManagerService.java
 @Override
 public final int startActivity(IApplicationThread caller, String callingPackage,
   String callingFeatureId, Intent intent, String resolvedType, IBinder resultTo,
   String resultWho, int requestCode, int startFlags, ProfilerInfo profilerInfo,
   Bundle bOptions) {
  return startActivityAsUser(caller, callingPackage, callingFeatureId, intent, resolvedType,
    resultTo, resultWho, requestCode, startFlags, profilerInfo, bOptions,
    UserHandle.getCallingUserId());
 }
 
 @Override
 public int startActivityAsUser(IApplicationThread caller, String callingPackage,
   String callingFeatureId, Intent intent, String resolvedType, IBinder resultTo,
   String resultWho, int requestCode, int startFlags, ProfilerInfo profilerInfo,
   Bundle bOptions, int userId) {
  return startActivityAsUser(caller, callingPackage, callingFeatureId, intent, resolvedType,
    resultTo, resultWho, requestCode, startFlags, profilerInfo, bOptions, userId,
    true /*validateIncomingUser*/);
 }
 
 private int startActivityAsUser(IApplicationThread caller, String callingPackage,
   @Nullable String callingFeatureId, Intent intent, String resolvedType,
   IBinder resultTo, String resultWho, int requestCode, int startFlags,
   ProfilerInfo profilerInfo, Bundle bOptions, int userId, boolean validateIncomingUser) {
	 ...
  userId = getActivityStartController().checkTargetUser(userId, validateIncomingUser,
    Binder.getCallingPid(), Binder.getCallingUid(), "startActivityAsUser");
    
  return getActivityStartController().obtainStarter(intent, "startActivityAsUser")
    .setCaller(caller)
    .setCallingPackage(callingPackage)
    .setCallingFeatureId(callingFeatureId)
    .setResolvedType(resolvedType)
    .setResultTo(resultTo)
    .setResultWho(resultWho)
    .setRequestCode(requestCode)
    .setStartFlags(startFlags)
    .setProfilerInfo(profilerInfo)
    .setActivityOptions(bOptions)
    .setUserId(userId)
    .execute();
 }
 
 ActivityStarter obtainStarter(Intent intent, String reason) {
  return mFactory.obtain().setIntent(intent).setReason(reason);
 }

上面幾步主要是做權限檢查

ActivityStarter.java
 int execute() {
 ...
 res = executeRequest(mRequest);
 ...
 }
//層層調用會到下面這個方法
ActivityStack.java
 private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {
 ...
 if (mResumedActivity != null) {
  pausing |= startPausingLocked(userLeaving, false , next);
 }
 ...
 mStackSupervisor.startSpecificActivity(next, true, false);
 ...
 }

startPausingLocked方法主要是通知Launcher進入Paused狀態(tài),在它進入這個狀態(tài)后,在ActivityStackSupervisor.startSpecificActivity方法判斷新的App進程狀態(tài)做出不同響應,如下:

ActivityStackSupervisor.java
void startSpecificActivity(ActivityRecord r, boolean andResume, boolean checkConfig) {
  // 獲取要啟動的Activity進程信息
  final WindowProcessController wpc =
    mService.getProcessController(r.processName, r.info.applicationInfo.uid);
  boolean knownToBeDead = false;
  //如果進程存在且有進程中有線程存在 就是啟動一個同應用的Activity(普通Activity就在此執(zhí)行)
  if (wpc != null && wpc.hasThread()) {
   try {
    realStartActivityLocked(r, wpc, 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.
   knownToBeDead = true;
  }
	//否則通過AMS向Zygote進程請求創(chuàng)建新的進程
  r.notifyUnknownVisibilityLaunchedForKeyguardTransition();
  final boolean isTop = andResume && r.isTopRunningActivity();
  mService.startProcessAsync(r, knownToBeDead, isTop, isTop ? "top-activity" : "activity");
}

截止到這里完成了Launcher和AMS的通信,以及AMS和Zygote進程的通信,接下來我們要創(chuàng)建要啟動的App的線程,即ActivityThread。

3.新的進程啟動,ActivityThread的main函數入口

上一部分Zygote啟動新的進程時標記ActivityThread.main函數,在Zygote創(chuàng)建好新進程后通過反射調用此方法,現在處于新App的進程中。

ActivityThread.java
 public static void main(String[] args) {
  ...
  Looper.prepareMainLooper();
	...
  ActivityThread thread = new ActivityThread();
  thread.attach(false, startSeq);
	...
  Looper.loop();
	...
 }
 
 private void attach(boolean system, long startSeq) {
   final IActivityManager mgr = ActivityManager.getService();
   try {
    mgr.attachApplication(mAppThread, startSeq);
   } catch (RemoteException ex) {
    throw ex.rethrowFromSystemServer();
   }
   ...
 }
ActivityManagerService.java
 private boolean attachApplicationLocked(@NonNull IApplicationThread thread,
   int pid, int callingUid, long startSeq) {
   ...
   thread.bindApplication(processName, appInfo, providerList,
      instr2.mClass,
      profilerInfo, instr2.mArguments,
      instr2.mWatcher,
      instr2.mUiAutomationConnection, testMode,
      mBinderTransactionTrackingEnabled, enableTrackAllocation,
      isRestrictedBackupMode || !normalMode, app.isPersistent(),
      new Configuration(app.getWindowProcessController().getConfiguration()),
      app.compat, getCommonServicesLocked(app.isolated),
      mCoreSettingsObserver.getCoreSettingsLocked(),
      buildSerial, autofillOptions, contentCaptureOptions,
      app.mDisabledCompatChanges);
    ...
    didSomething = mAtmInternal.attachApplication(app.getWindowProcessController());
    ...
 }

這里主要是創(chuàng)建了Looper和ActivityThread對象,然后將當前應用ApplicationThread注冊到AMS中,ApplicationThread是ActivityThread的內部類實現了IApplicationThread.Stub用此對象可跨進程通信,上面的代碼邏輯分兩步,第一步,在AMS綁定ApplicationThread時,發(fā)送了一個H.BIND_APPLICATION的Message,在Handler中處理該消息時調用了Application的onCreate方法,第二步,在mAtmInternal的attachApplication層層調用到ActivityStackSupervisor.realStartActivityLocked方法,整體如下:

public final void bindApplication(String processName, ApplicationInfo appInfo,
    ProviderInfoList providerList, ComponentName instrumentationName,
    ProfilerInfo profilerInfo, Bundle instrumentationArgs,
    IInstrumentationWatcher instrumentationWatcher,
    IUiAutomationConnection instrumentationUiConnection, int debugMode,
    boolean enableBinderTracking, boolean trackAllocation,
    boolean isRestrictedBackupMode, boolean persistent, Configuration config,
    CompatibilityInfo compatInfo, Map services, Bundle coreSettings,
    String buildSerial, AutofillOptions autofillOptions,
    ContentCaptureOptions contentCaptureOptions, long[] disabledCompatChanges) {
    	...
    	sendMessage(H.BIND_APPLICATION, data);
 }
    
public void handleMessage(Message msg) {
 switch (msg.what) {
  case BIND_APPLICATION:
  	AppBindData data = (AppBindData)msg.obj;
  	handleBindApplication(data);
  	Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
  	break;
  ...
  }
}

private void handleBindApplication(AppBindData data) {
	...
	mInstrumentation.callApplicationOnCreate(app);
	...
}

到這里為止,新的App線程已經啟動并且綁定了Application。

4.創(chuàng)建Activity

ActivityStackSupervisor.java
boolean realStartActivityLocked(ActivityRecord r, WindowProcessController proc,
  boolean andResume, boolean checkConfig) throws RemoteException {
  ...
  final ClientTransaction clientTransaction = ClientTransaction.obtain(
    proc.getThread(), r.appToken);
   final DisplayContent dc = r.getDisplay().mDisplayContent;
   clientTransaction.addCallback(LaunchActivityItem.obtain(new Intent(r.intent),
     System.identityHashCode(r), r.info,
     mergedConfiguration.getGlobalConfiguration(),
     mergedConfiguration.getOverrideConfiguration(), r.compat,
     r.launchedFromPackage, task.voiceInteractor, proc.getReportedProcState(),
     r.getSavedState(), r.getPersistentSavedState(), results, newIntents,
     dc.isNextTransitionForward(), proc.createProfilerInfoIfNeeded(),
     r.assistToken, r.createFixedRotationAdjustmentsIfNeeded()));

   final ActivityLifecycleItem lifecycleItem;
   if (andResume) {
    lifecycleItem = ResumeActivityItem.obtain(dc.isNextTransitionForward());
   } else {
    lifecycleItem = PauseActivityItem.obtain();
   }
   clientTransaction.setLifecycleStateRequest(lifecycleItem);
   //執(zhí)行clientTransaction
   mService.getLifecycleManager().scheduleTransaction(clientTransaction);
   ...
}

ClientTransaction管理了Activity的啟動信息,由ClientLifecycleManager執(zhí)行,scheduleTransaction方法中發(fā)送了EXECUTE_TRANSACTION的消息給ActivityThread的H類處理,然后執(zhí)行TransactionExecutor.execute(),之后執(zhí)行handleLaunchActivity方法,如下

 void scheduleTransaction(ClientTransaction transaction) throws RemoteException {
  final IApplicationThread client = transaction.getClient();
  transaction.schedule();
  ...
 }

 public void schedule() throws RemoteException {
  mClient.scheduleTransaction(this);
 }

 void scheduleTransaction(ClientTransaction transaction) {
  transaction.preExecute(this);
  sendMessage(ActivityThread.H.EXECUTE_TRANSACTION, transaction);
 }

 class H extends Handler {
   ...
   public void handleMessage(Message msg) {
   ...
   case EXECUTE_TRANSACTION:
    final ClientTransaction transaction = (ClientTransaction) msg.obj;
    mTransactionExecutor.execute(transaction);
    if (isSystem()) {
     transaction.recycle();
    }
    break;
   ...
   } 
   ...
 }

 public void execute(ClientTransactionHandler client, IBinder token,
   PendingTransactionActions pendingActions) {
  ...
  client.handleLaunchActivity(r, pendingActions, null /* customIntent */);
 }

接下來由ActivityThread來處理后續(xù)操作

public Activity handleLaunchActivity(ActivityClientRecord r,
   PendingTransactionActions pendingActions, Intent customIntent) {
  ...
  final Activity a = performLaunchActivity(r, customIntent);
  ...
  return a;
}

private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
  ContextImpl appContext = createBaseContextForActivity(r);
  ...
  java.lang.ClassLoader cl = appContext.getClassLoader();
  activity = mInstrumentation.newActivity(cl, component.getClassName(), r.intent);
  ...
  Application app = r.packageInfo.makeApplication(false, mInstrumentation);
  ...
  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, window, r.configCallback,
      r.assistToken);
  ...
  activity.setTheme(theme);
  ...
  mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
}

performLaunchActivity方法中主要做了以下幾件事:

  1. 創(chuàng)建要啟動activity的上下文環(huán)境
  2. 通過Instrumentation的newActivity方法,以反射形式創(chuàng)建activity實例
  3. 如果Application不存在的話會創(chuàng)建Application并調用Application的onCreate方法
  4. 初始化Activity,創(chuàng)建Window對象(PhoneWindow)并實現Activity和Window相關聯
  5. 通過Instrumentation調用Activity的onCreate方法

總結

根Activity整體上學習意義較大,建議從整體流程入手,遇到流程不通時也可以debug。 Activity的整體啟動流程:

  1. 點擊圖標,Launcher向AMS請求啟動該App
  2. AMS反饋收到啟動請求,并告知Launcher進入pause狀態(tài)
  3. Launcher進入Paused狀態(tài)并告知AMS
  4. AMS檢測新的App是否已啟動,否則通知Zygote創(chuàng)建新的進程并啟動ActivityThread.main()
  5. 應用進程啟動ActivityThread
  6. ActivityThread中H處理需要啟動Activity的請求消息

以上就是詳解Android Activity的啟動流程的詳細內容,更多關于Android Activity的啟動流程的資料請關注腳本之家其它相關文章!

相關文章

  • Kotlin類型系統(tǒng)竟如此簡單

    Kotlin類型系統(tǒng)竟如此簡單

    這篇文章主要給大家介紹了關于Kotlin類型系統(tǒng)的相關資料,文中通過示例代碼介紹的非常詳細,對大家學習或者使用Kotlin具有一定的參考學習價值,需要的朋友們下面來一起學習學習吧
    2019-09-09
  • Android仿淘寶商品拖動查看詳情及標題欄漸變功能

    Android仿淘寶商品拖動查看詳情及標題欄漸變功能

    這篇文章主要介紹了Android仿淘寶商品拖動查看詳情及標題欄漸變功能,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2016-09-09
  • Android獲取手機信息的工具類

    Android獲取手機信息的工具類

    這篇文章主要為大家詳細介紹了Android獲取手機信息的工具類,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-09-09
  • 完整的Android MVP開發(fā)之旅

    完整的Android MVP開發(fā)之旅

    這篇文章主要為大家介紹了完整的Android MVP開發(fā)之旅,總結自己開發(fā)Android MVP的全過程,感興趣的小伙伴們可以參考一下
    2016-02-02
  • Kotlin協程開發(fā)之Flow的融合與Channel容量及溢出策略介紹

    Kotlin協程開發(fā)之Flow的融合與Channel容量及溢出策略介紹

    這篇文章主要介紹了Kotlin協程:Flow的融合、Channel容量、溢出策略,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2022-09-09
  • android設置adb自帶screenrecord錄屏命令

    android設置adb自帶screenrecord錄屏命令

    這篇文章主要介紹了android設置adb自帶screenrecord錄屏命令,需要的朋友可以參考下
    2018-11-11
  • Android圖片加載案例分享

    Android圖片加載案例分享

    這篇文章主要為大家分享了Android圖片加載的實現代碼,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-05-05
  • Android中Split()字符串分割特殊用法案例詳解

    Android中Split()字符串分割特殊用法案例詳解

    本文通過案例的形式給大家詳細介紹了android中split()字符串分割特殊用法的知識,非常不錯具有參考借鑒價值,感興趣的朋友參考下
    2016-11-11
  • com.android.support版本沖突解決方法

    com.android.support版本沖突解決方法

    在本篇文章里小編給大家整理的是關于com.android.support版本沖突解決方法以及相關知識點,需要的朋友們學習下。
    2019-09-09
  • Android修改Dialog樣式的方法

    Android修改Dialog樣式的方法

    Android 對話框支持自定義標題,內容,按鈕和點擊事件,基本上可以滿足我們日常的使用。 但有時候我們想要修改對話框的文字,按鈕顏色等,系統(tǒng)并沒有提供對應的方法,正常情況下只能自定義布局。 接下來通過源碼解析介紹幾種修改 Dialog樣式的方法。
    2021-05-05

最新評論