中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Android組件Activity的啟動過程是什么

發布時間:2023-04-15 16:45:54 來源:億速云 閱讀:108 作者:iii 欄目:開發技術

這篇文章主要介紹了Android組件Activity的啟動過程是什么的相關知識,內容詳細易懂,操作簡單快捷,具有一定借鑒價值,相信大家閱讀完這篇Android組件Activity的啟動過程是什么文章都會有所收獲,下面我們一起來看看吧。

在分析之前,我先介紹幾個類:
  • Activity:這個大家都熟悉,startActivity方法的真正實現在Activity中

  • Instrumentation:用來輔助Activity完成啟動Activity的過程

  • ActivityThread(包含ApplicationThread + ApplicationThreadNative +IApplicationThread):真正啟動Activity的實現都在這里

源碼分析

首先看入口

code:Activity#startActivity

@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) { 
 startActivityForResult(intent, requestCode, null); 
}

說明:顯然,從上往下,最終都是由startActivityForResult來實現的

接著看

code:Activity#startActivityForResult

public void startActivityForResult(Intent intent, int requestCode, Bundle options) { 
 //一般的Activity其mParent為null,mParent常用在ActivityGroup中,ActivityGroup已廢棄 
 if (mParent == null) { 
  //這里會啟動新的Activity,核心功能都在mMainThread.getApplicationThread()中完成 
  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) { 
   // 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 { 
  //在ActivityGroup內部的Activity調用startActivity的時候會走到這里,內部處理邏輯和上面是類似的 
  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); 
  } 
 } 
}

說明:上述代碼關鍵點都有注釋了,可以發現,真正打開activity的實現在Instrumentation的execStartActivity方法中,去看看

code:Instrumentation#execStartActivity

public ActivityResult execStartActivity( 
  Context who, IBinder contextThread, IBinder token, Activity target, 
  Intent intent, int requestCode, Bundle options) { 
 //核心功能在這個whoThread中完成,其內部scheduleLaunchActivity方法用于完成activity的打開 
 IApplicationThread whoThread = (IApplicationThread) contextThread; 
 if (mActivityMonitors != null) { 
  synchronized (mSync) { 
   //先查找一遍看是否存在這個activity 
   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++; 
     //如果目標activity無法打開,直接return 
     if (am.isBlocking()) { 
      return requestCode  = 0 ? am.getResult() : null; 
     } 
     break; 
    } 
   } 
  } 
 } 
 try { 
  intent.migrateExtraStreamToClipData(); 
  intent.prepareToLeaveProcess(); 
  //這里才是真正打開activity的地方,核心功能在whoThread中完成。 
  int result = ActivityManagerNative.getDefault() 
   .startActivity(whoThread, who.getBasePackageName(), intent, 
     intent.resolveTypeIfNeeded(who.getContentResolver()), 
     token, target != null ? target.mEmbeddedID : null, 
     requestCode, 0, null, null, options); 
  //這個方法是專門拋異常的,它會對結果進行檢查,如果無法打開activity, 
  //則拋出諸如ActivityNotFoundException類似的各種異常 
  checkStartActivityResult(result, intent); 
 } catch (RemoteException e) { 
 } 
 return null; 
}

說明:我想再說一下這個方法checkStartActivityResult,它也專業拋異常的,看代碼,相信大家對下面的異常信息不陌生吧,就是它干的,其中最熟悉的非Unable to find explicit activity class莫屬了,如果你在xml中沒有注冊目標activity,此異常將會拋出。

/*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); 
  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"); 
  default: 
   throw new AndroidRuntimeException("Unknown error code " 
     + res + " when starting " + intent); 
 } 
}

接下來我們要去看看IApplicationThread,因為核心功能由其內部的scheduleLaunchActivity方法來完成,由于IApplicationThread是個接口,所以,我們需要找到它的實現類,我已經幫大家找到了,它就是ActivityThread中的內部類ApplicationThread,看下它的繼承關系:

private class ApplicationThread extends ApplicationThreadNative;

public abstract class ApplicationThreadNative extends Binder implements IApplicationThread;

可以發現,ApplicationThread還是間接實現了IApplicationThread接口,先看下這個類的結構

Android組件Activity的啟動過程是什么

看完ApplicationThread的大致結構,我們應該能夠猜測到,Activity的生命周期中的resume、newIntent、pause、stop等事件都是由它觸發的,事實上,的確是這樣的。這里,我們為了說明問題,僅僅看scheduleLaunchActivity方法

code:ApplicationThread#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) { 
 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); 
 queueOrSendMessage(H.LAUNCH_ACTIVITY, r); 
}

說明:上述代碼很好理解,構造一個activity記錄,然后發送一個消息,所以,我們要看看Handler是如何處理這個消息的,現在轉到這個Handler,它有個很短的名字叫做H

code:ActivityThread#H

//這個類太長,我只帖出了我們用到的部分 
private class H extends Handler { 
 public void handleMessage(Message msg) { 
  if (DEBUG_MESSAGES) Slog.v(TAG, "    handling: " + codeToString(msg.what)); 
  switch (msg.what) { 
   //這里處理LAUNCH_ACTIVITY消息類型 
   case LAUNCH_ACTIVITY: { 
    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStart"); 
    ActivityClientRecord r = (ActivityClientRecord)msg.obj; 
    r.packageInfo = getPackageInfoNoCheck( 
      r.activityInfo.applicationInfo, r.compatInfo); 
    //這里處理startActivity消息 
    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 != 0, msg.arg2); 
    maybeSnapshot(); 
    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); 
    break; 
   ... 
  } 
}

說明:看來還要看handleLaunchActivity

code:ActivityThread#handleLaunchActivity

private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent) { 
// If we are getting ready to gc after going to the background, well 
// we are back active so skip it. 
unscheduleGcIdler(); 
if (r.profileFd != null) { 
mProfiler.setProfiler(r.profileFile, r.profileFd); 
mProfiler.startProfiling(); 
mProfiler.autoStopProfiler = r.autoStopProfiler; 
} 
// Make sure we are running with the most recent config. 
handleConfigurationChanged(null, null); 
if (localLOGV) Slog.v( 
TAG, "Handling launch of " + r); 
//終于到底了,大家都有點不耐煩了吧,從方法名可以看出, 
//performLaunchActivity真正完成了activity的調起, 
//同時activity會被實例化,并且onCreate會被調用 
Activity a = performLaunchActivity(r, customIntent); 
if (a != null) { 
r.createdConfig = new Configuration(mConfiguration); 
Bundle oldState = r.state; 
//看到沒,目標activity的onResume會被調用 
handleResumeActivity(r.token, false, r.isForward, 
!r.activity.mFinished && !r.startsNotResumed); 
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. 
try { 
r.activity.mCalled = false; 
//同時,由于新activity被調起了,原activity的onPause會被調用 
mInstrumentation.callActivityOnPause(r.activity); 
// 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; 
} 
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 { 
// 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); 
} catch (RemoteException ex) { 
// Ignore 
} 
} 
}

說明:關于原activity和新activity之間的狀態同步,如果大家感興趣可以自己研究下,因為邏輯太復雜,我沒法把所有問題都說清楚,否則就太深入細節而淹沒了整體邏輯,研究源碼要的就是清楚整體邏輯。下面看最后一個方法,這個方法是activity的啟動過程的真正實現。

code:ActivityThread#performLaunchActivity

private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) { 
// System.out.println("##### [" + System.currentTimeMillis() + "] ActivityThread.performLaunchActivity(" + r + ")"); 
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(); 
//用ClassLoader(類加載器)將目標activity的類通過類名加載進來并調用newInstance來實例化一個對象 
//其實就是通過Activity的無參構造方法來new一個對象,對象就是在這里new出來的。 
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) { 
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(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被調用了,到此為止,Activity被啟動了,接下來的流程就是Activity的生命周期了, 
//本文之前已經提到,其生命周期的各種狀態的切換由ApplicationThread內部來完成 
mInstrumentation.callActivityOnCreate(activity, r.state); 
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.state != null) { 
mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state); 
} 
} 
if (!r.activity.mFinished) { 
activity.mCalled = false; 
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); 
} 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; 
}

關于“Android組件Activity的啟動過程是什么”這篇文章的內容就介紹到這里,感謝各位的閱讀!相信大家對“Android組件Activity的啟動過程是什么”知識都有一定的了解,大家如果還想學習更多知識,歡迎關注億速云行業資訊頻道。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

蒙城县| 禹城市| 莫力| 扎鲁特旗| 龙海市| 宁蒗| 安顺市| 耒阳市| 芜湖县| 尉犁县| 白朗县| 云和县| 射洪县| 房山区| 上犹县| 班戈县| 平遥县| 兰西县| 鞍山市| 肇源县| 临武县| 遵义县| 陕西省| 绵竹市| 古浪县| 西昌市| 巴塘县| 获嘉县| 建平县| 巩留县| 区。| 汝南县| 肇源县| 治多县| 柳江县| 海阳市| 兴隆县| 泸西县| 嘉兴市| 富平县| 彰武县|