一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務(wù)器之家:專注于服務(wù)器技術(shù)及軟件下載分享
分類導(dǎo)航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術(shù)|正則表達(dá)式|C/C++|IOS|C#|Swift|Android|VB|R語(yǔ)言|JavaScript|易語(yǔ)言|vb.net|

服務(wù)器之家 - 編程語(yǔ)言 - Android - Android Activity的啟動(dòng)過(guò)程源碼解析

Android Activity的啟動(dòng)過(guò)程源碼解析

2022-02-17 17:15singwhatiwanna Android

這篇文章主要介紹了Android Activity的啟動(dòng)過(guò)程源碼解析,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧

前言

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

  1. Activity:這個(gè)大家都熟悉,startActivity方法的真正實(shí)現(xiàn)在Activity中
  2. Instrumentation:用來(lái)輔助Activity完成啟動(dòng)Activity的過(guò)程
  3. ActivityThread(包含ApplicationThread + ApplicationThreadNative + IApplicationThread):真正啟動(dòng)Activity的實(shí)現(xiàn)都在這里

源碼分析

首先看入口

code:Activity#startActivity

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
@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);
}

說(shuō)明:顯然,從上往下,最終都是由startActivityForResult來(lái)實(shí)現(xiàn)的

接著看

code:Activity#startActivityForResult

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
public void startActivityForResult(Intent intent, int requestCode, Bundle options) {
 //一般的Activity其mParent為null,mParent常用在ActivityGroup中,ActivityGroup已廢棄
 if (mParent == null) {
  //這里會(huì)啟動(dòng)新的Activity,核心功能都在mMainThread.getApplicationThread()中完成
  Instrumentation.ActivityResult ar =
   mInstrumentation.execStartActivity(
    this, mMainThread.getApplicationThread(), mToken, this,
    intent, requestCode, options);
  if (ar != null) {
   //發(fā)送結(jié)果,即onActivityResult會(huì)被調(diào)用
   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內(nèi)部的Activity調(diào)用startActivity的時(shí)候會(huì)走到這里,內(nèi)部處理邏輯和上面是類似的
  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);
  }
 }
}

說(shuō)明:上述代碼關(guān)鍵點(diǎn)都有注釋了,可以發(fā)現(xiàn),真正打開(kāi)activity的實(shí)現(xiàn)在Instrumentation的execStartActivity方法中,去看看

code:Instrumentation#execStartActivity

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
public ActivityResult execStartActivity(
  Context who, IBinder contextThread, IBinder token, Activity target,
  Intent intent, int requestCode, Bundle options) {
 //核心功能在這個(gè)whoThread中完成,其內(nèi)部scheduleLaunchActivity方法用于完成activity的打開(kāi)
 IApplicationThread whoThread = (IApplicationThread) contextThread;
 if (mActivityMonitors != null) {
  synchronized (mSync) {
   //先查找一遍看是否存在這個(gè)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)) {
     //如果找到了就跳出循環(huán)
     am.mHits++;
     //如果目標(biāo)activity無(wú)法打開(kāi),直接return
     if (am.isBlocking()) {
      return requestCode >= 0 ? am.getResult() : null;
     }
     break;
    }
   }
  }
 }
 try {
  intent.migrateExtraStreamToClipData();
  intent.prepareToLeaveProcess();
  //這里才是真正打開(kāi)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);
  //這個(gè)方法是專門拋異常的,它會(huì)對(duì)結(jié)果進(jìn)行檢查,如果無(wú)法打開(kāi)activity,
  //則拋出諸如ActivityNotFoundException類似的各種異常
  checkStartActivityResult(result, intent);
 } catch (RemoteException e) {
 }
 return null;
}

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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
/*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);
 }
}

接下來(lái)我們要去看看IApplicationThread,因?yàn)楹诵墓δ苡善鋬?nèi)部的scheduleLaunchActivity方法來(lái)完成,由于IApplicationThread是個(gè)接口,所以,我們需要找到它的實(shí)現(xiàn)類,我已經(jīng)幫大家找到了,它就是ActivityThread中的內(nèi)部類ApplicationThread,看下它的繼承關(guān)系:

private class ApplicationThread extends ApplicationThreadNative;

public abstract class ApplicationThreadNative extends Binder implements IApplicationThread;

可以發(fā)現(xiàn),ApplicationThread還是間接實(shí)現(xiàn)了IApplicationThread接口,先看下這個(gè)類的結(jié)構(gòu)

Android Activity的啟動(dòng)過(guò)程源碼解析

看完ApplicationThread的大致結(jié)構(gòu),我們應(yīng)該能夠猜測(cè)到,Activity的生命周期中的resume、newIntent、pause、stop等事件都是由它觸發(fā)的,事實(shí)上,的確是這樣的。這里,我們?yōu)榱苏f(shuō)明問(wèn)題,僅僅看scheduleLaunchActivity方法

code:ApplicationThread#scheduleLaunchActivity

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
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);
}

說(shuō)明:上述代碼很好理解,構(gòu)造一個(gè)activity記錄,然后發(fā)送一個(gè)消息,所以,我們要看看Handler是如何處理這個(gè)消息的,現(xiàn)在轉(zhuǎn)到這個(gè)Handler,它有個(gè)很短的名字叫做H

code:ActivityThread#H

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
//這個(gè)類太長(zhǎng),我只帖出了我們用到的部分
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;
   ...
  }
}

說(shuō)明:看來(lái)還要看handleLaunchActivity

code:ActivityThread#handleLaunchActivity

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
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);
 //終于到底了,大家都有點(diǎn)不耐煩了吧,從方法名可以看出,
 //performLaunchActivity真正完成了activity的調(diào)起,
 //同時(shí)activity會(huì)被實(shí)例化,并且onCreate會(huì)被調(diào)用
 Activity a = performLaunchActivity(r, customIntent);
 
 if (a != null) {
  r.createdConfig = new Configuration(mConfiguration);
  Bundle oldState = r.state;
  //看到?jīng)],目標(biāo)activity的onResume會(huì)被調(diào)用
  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;
    //同時(shí),由于新activity被調(diào)起了,原activity的onPause會(huì)被調(diào)用
    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
  }
 }
}

說(shuō)明:關(guān)于原activity和新activity之間的狀態(tài)同步,如果大家感興趣可以自己研究下,因?yàn)檫壿嬏珡?fù)雜,我沒(méi)法把所有問(wèn)題都說(shuō)清楚,否則就太深入細(xì)節(jié)而淹沒(méi)了整體邏輯,研究源碼要的就是清楚整體邏輯。下面看最后一個(gè)方法,這個(gè)方法是activity的啟動(dòng)過(guò)程的真正實(shí)現(xiàn)。

code:ActivityThread#performLaunchActivity

?

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
      46
      47
      48
      49
      50
      51
      52
      53
      54
      55
      56
      57
      58
      59
      60
      61
      62
      63
      64
      65
      66
      67
      68
      69
      70
      71
      72
      73
      74
      75
      76
      77
      78
      79
      80
      81
      82
      83
      84
      85
      86
      87
      88
      89
      90
      91
      92
      93
      94
      95
      96
      97
      98
      99
      100
      101
      102
      103
      104
      105
      106
      107
      108
      109
      110
      111
      112
      113
      114
      115
      116
      117
      118
      119
      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中解析出目標(biāo)activity的啟動(dòng)參數(shù)
       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(類加載器)將目標(biāo)activity的類通過(guò)類名加載進(jìn)來(lái)并調(diào)用newInstance來(lái)實(shí)例化一個(gè)對(duì)象
        //其實(shí)就是通過(guò)Activity的無(wú)參構(gòu)造方法來(lái)new一個(gè)對(duì)象,對(duì)象就是在這里new出來(lái)的。
        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 id="codetool">

      總結(jié)

      相信當(dāng)你看到這里的時(shí)候,你對(duì)Activity的啟動(dòng)過(guò)程應(yīng)該有了一個(gè)感性的認(rèn)識(shí)。Activity很復(fù)雜,特性很多,本文沒(méi)法對(duì)各個(gè)細(xì)節(jié)進(jìn)行深入分析,而且就算真的對(duì)各個(gè)細(xì)節(jié)都進(jìn)行了深入分析,那文章要有多長(zhǎng)啊,還有人有耐心看下去嗎?希望本文能夠給大家?guī)?lái)一些幫助,謝謝大家閱讀。 也希望大家多多支持服務(wù)器之家。

      原文鏈接:https://blog.csdn.net/singwhatiwanna/article/details/18154335

      延伸 · 閱讀

      精彩推薦
      主站蜘蛛池模板: 久久婷婷五月综合色精品首页 | 国产亚洲精品一区二区在线观看 | 国产偷啪视频一区 | 纲手被强喷水羞羞漫画 | 精品一区二区三区五区六区 | 逼里逼里香 | 日本javaajax| 男人天堂999 | 大陆国语自产精品视频在 | 男人的天堂欧美 | 护士柔佳 | 国产中文在线视频 | 国产精品美女福利视频免费专区 | 69日本xxxxxxxxx98| 电车痴汉中文字幕 | 18亚洲chinese男男1069 | 窝窝午夜理伦影院 | 日韩一区在线播放 | 亚洲色图欧美色 | 欧美日韩精品一区二区三区视频 | 无敌在线视频观看免费 | 亚洲高清中文字幕一区二区三区 | 午夜久久久久久网站 | 国语精彩对白2021 | 四虎影院在线免费观看视频 | 亚洲AV 无码AV 中文字幕 | 国产特黄一级一片免费 | 国产福利自产拍在线观看 | 青青热久免费精品视频网站 | 日韩福利网 | 成人免费播放 | 日韩欧美不卡片 | 四虎884aa永久播放地址http | 久久嫩草影院网站 | 性xxxx中国 | 色图图片 | 美琪美腿白丝交小说 | 免费一级欧美片在线观看 | 免费在线观看小视频 | 羲义嫁密着中出交尾gvg794 | 国产精品久久久久久久牛牛 |