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

首頁 > 系統 > Android > 正文

Android Activity的啟動過程源碼解析

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

前言

Activity是Android中一個很重要的概念,堪稱四大組件之首,關于Activity有很多內容,比如生命周期和啟動Flags,這二者想要說清楚,恐怕又要寫兩篇長文,更何況分析它們的源碼呢。不過本文的側重點不是它們,我要介紹的是一個Activity典型的啟動過程,本文會從源碼的角度對其進行分析。我們知道,當startActivity被調用的時候,可以啟動一個Activity,但是你知道這個Activity是如何被啟動的嗎?每個Activity也是一個對象,你知道這個對象是啥時候被創建的嗎(也就是說它的構造方法是什么時候被調用的)?為什么onCreate是Activity的執行入口?所有的這一切都被系統封裝好了,對我們來說是透明的,我們使用的時候僅僅是傳遞一個intent然后startActivity就可以達到目的了,不過,閱讀了本文以后,你將會了解它的背后到底做了哪些事情。在分析之前,我先介紹幾個類:

  1. Activity:這個大家都熟悉,startActivity方法的真正實現在Activity中
  2. Instrumentation:用來輔助Activity完成啟動Activity的過程
  3. 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   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; } 

總結

相信當你看到這里的時候,你對Activity的啟動過程應該有了一個感性的認識。Activity很復雜,特性很多,本文沒法對各個細節進行深入分析,而且就算真的對各個細節都進行了深入分析,那文章要有多長啊,還有人有耐心看下去嗎?希望本文能夠給大家帶來一些幫助,謝謝大家閱讀。 也希望大家多多支持VEVB武林網。


注:相關教程知識閱讀請移步到Android開發頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 宿迁市| 哈密市| 广南县| 明溪县| 廉江市| 得荣县| 文成县| 肃南| 德格县| 北安市| 鹿邑县| 孝义市| 盐津县| 定日县| 马公市| 湟中县| 梧州市| 册亨县| 临漳县| 汝州市| 洪湖市| 固始县| 平遥县| 元阳县| 南宁市| 延边| 红河县| 喀什市| 洪泽县| 仁布县| 阿克苏市| 西华县| 桐庐县| 罗田县| 鸡东县| 新竹县| 宣恩县| 西乌| 顺义区| 漳州市| 陇西县|