Skip to content

Commit 2f97357

Browse files
committed
2 parents 66dda0f + bbdf066 commit 2f97357

10 files changed

+804
-16
lines changed
Lines changed: 385 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,385 @@
1+
Activity启动过程
2+
===
3+
4+
前两天面试了天猫的开发,被问到了`Activity`启动过程,不懂啊....
5+
今天就来分析一下,我们开启`Activity`主要有两种方式:
6+
7+
- 通过桌面图标启动,桌面就是`Launcher`其实他也是一个应用程序,他也是继承`Activity`
8+
- 在程序内部调用`startActivity()`开启。
9+
10+
`Launcher`点击图标其实也是调用了`Activity``startActivity()`方法,所以我们就从`startActivity()`方法入手了。
11+
首先看一下`Activity`类中的`startActivity()`方法:
12+
```java
13+
@Override
14+
public void startActivity(Intent intent) {
15+
this.startActivity(intent, null);
16+
}
17+
```
18+
继续看`startActivity(intent, null)`:
19+
```java
20+
/**
21+
* Launch a new activity. You will not receive any information about when
22+
* the activity exits. This implementation overrides the base version,
23+
* providing information about
24+
* the activity performing the launch. Because of this additional
25+
* information, the {@link Intent#FLAG_ACTIVITY_NEW_TASK} launch flag is not
26+
* required; if not specified, the new activity will be added to the
27+
* task of the caller.
28+
*
29+
* <p>This method throws {@link android.content.ActivityNotFoundException}
30+
* if there was no Activity found to run the given Intent.
31+
*
32+
* @param intent The intent to start.
33+
* @param options Additional options for how the Activity should be started.
34+
* See {@link android.content.Context#startActivity(Intent, Bundle)
35+
* Context.startActivity(Intent, Bundle)} for more details.
36+
*
37+
* @throws android.content.ActivityNotFoundException
38+
*
39+
* @see {@link #startActivity(Intent)}
40+
* @see #startActivityForResult
41+
*/
42+
@Override
43+
public void startActivity(Intent intent, @Nullable Bundle options) {
44+
if (options != null) {
45+
startActivityForResult(intent, -1, options);
46+
} else {
47+
// Note we want to go through this call for compatibility with
48+
// applications that may have overridden the method.
49+
startActivityForResult(intent, -1);
50+
}
51+
}
52+
```
53+
接下来会调用`startActivityForResult()`方法(注释也很重要啊,里面也说明了singleTask启动模式时该方法不会走到回调中):
54+
```java
55+
/**
56+
* Launch an activity for which you would like a result when it finished.
57+
* When this activity exits, your
58+
* onActivityResult() method will be called with the given requestCode.
59+
* Using a negative requestCode is the same as calling
60+
* {@link #startActivity} (the activity is not launched as a sub-activity).
61+
*
62+
* <p>Note that this method should only be used with Intent protocols
63+
* that are defined to return a result. In other protocols (such as
64+
* {@link Intent#ACTION_MAIN} or {@link Intent#ACTION_VIEW}), you may
65+
* not get the result when you expect. For example, if the activity you
66+
* are launching uses the singleTask launch mode, it will not run in your
67+
* task and thus you will immediately receive a cancel result.
68+
*
69+
* <p>As a special case, if you call startActivityForResult() with a requestCode
70+
* >= 0 during the initial onCreate(Bundle savedInstanceState)/onResume() of your
71+
* activity, then your window will not be displayed until a result is
72+
* returned back from the started activity. This is to avoid visible
73+
* flickering when redirecting to another activity.
74+
*
75+
* <p>This method throws {@link android.content.ActivityNotFoundException}
76+
* if there was no Activity found to run the given Intent.
77+
*
78+
* @param intent The intent to start.
79+
* @param requestCode If >= 0, this code will be returned in
80+
* onActivityResult() when the activity exits.
81+
* @param options Additional options for how the Activity should be started.
82+
* See {@link android.content.Context#startActivity(Intent, Bundle)
83+
* Context.startActivity(Intent, Bundle)} for more details.
84+
*
85+
* @throws android.content.ActivityNotFoundException
86+
*
87+
* @see #startActivity
88+
*/
89+
public void startActivityForResult(Intent intent, int requestCode, @Nullable Bundle options) {
90+
// mParent也是Activity类,通过名字就能看明白了。
91+
if (mParent == null) {
92+
// 开始了啊
93+
Instrumentation.ActivityResult ar =
94+
mInstrumentation.execStartActivity(
95+
this, mMainThread.getApplicationThread(), mToken, this,
96+
intent, requestCode, options);
97+
if (ar != null) {
98+
mMainThread.sendActivityResult(
99+
mToken, mEmbeddedID, requestCode, ar.getResultCode(),
100+
ar.getResultData());
101+
}
102+
if (requestCode >= 0) {
103+
// If this start is requesting a result, we can avoid making
104+
// the activity visible until the result is received. Setting
105+
// this code during onCreate(Bundle savedInstanceState) or onResume() will keep the
106+
// activity hidden during this time, to avoid flickering.
107+
// This can only be done when a result is requested because
108+
// that guarantees we will get information back when the
109+
// activity is finished, no matter what happens to it.
110+
mStartedActivity = true;
111+
}
112+
113+
cancelInputsAndStartExitTransition(options);
114+
// TODO Consider clearing/flushing other event sources and events for child windows.
115+
} else {
116+
if (options != null) {
117+
mParent.startActivityFromChild(this, intent, requestCode, options);
118+
} else {
119+
// Note we want to go through this method for compatibility with
120+
// existing applications that may have overridden it.
121+
mParent.startActivityFromChild(this, intent, requestCode);
122+
}
123+
}
124+
}
125+
```
126+
里面调用了`mInstrumentation.execStartActivity`这是啥玩意,先看一下`mInstrumentation`属性,他是`Instrumentation`类,我们看下文档
127+
```java
128+
/**
129+
* Base class for implementing application instrumentation code. When running
130+
* with instrumentation turned on, this class will be instantiated for you
131+
* before any of the application code, allowing you to monitor all of the
132+
* interaction the system has with the application. An Instrumentation
133+
* implementation is described to the system through an AndroidManifest.xml's
134+
* &lt;instrumentation&gt; tag.
135+
*/
136+
public class Instrumentation {
137+
...
138+
}
139+
```
140+
放狗查了下`Instrumentation`的意思是仪器、工具、装置的意思。我就大体翻一下(英语不好- -~,可能不准确)该类是实现应用程序代码的基类,当该类在
141+
启动的状态下运行时,该类会在其他任何应用程序运行前进行初始化,允许你件事所有应用程序与系统的交互。一个`Instrumentation`实例会通过`Manifest`文件
142+
中的`<instrumenttation`标签描述给系统。
143+
所以继续看一下`mInstrumentation.execStartActivity()`:
144+
```java
145+
/**
146+
// 下面的注释说的很明白了默认实现会更新任何活跃的对象并分发给系统的`activity manager`
147+
* Execute a startActivity call made by the application. The default
148+
* implementation takes care of updating any active {@link ActivityMonitor}
149+
* objects and dispatches this call to the system activity manager; you can
150+
* override this to watch for the application to start an activity, and
151+
* modify what happens when it does.
152+
*
153+
* <p>This method returns an {@link ActivityResult} object, which you can
154+
* use when intercepting application calls to avoid performing the start
155+
* activity action but still return the result the application is
156+
* expecting. To do this, override this method to catch the call to start
157+
* activity so that it returns a new ActivityResult containing the results
158+
* you would like the application to see, and don't call up to the super
159+
* class. Note that an application is only expecting a result if
160+
* <var>requestCode</var> is &gt;= 0.
161+
*
162+
* <p>This method throws {@link android.content.ActivityNotFoundException}
163+
* if there was no Activity found to run the given Intent.
164+
*
165+
* @param who The Context from which the activity is being started.
166+
* @param contextThread The main thread of the Context from which the activity
167+
* is being started.
168+
* @param token Internal token identifying to the system who is starting
169+
* the activity; may be null.
170+
* @param target Which activity is performing the start (and thus receiving
171+
* any result); may be null if this call is not being made
172+
* from an activity.
173+
* @param intent The actual Intent to start.
174+
* @param requestCode Identifier for this request's result; less than zero
175+
* if the caller is not expecting a result.
176+
* @param options Addition options.
177+
*
178+
* @return To force the return of a particular result, return an
179+
* ActivityResult object containing the desired data; otherwise
180+
* return null. The default implementation always returns null.
181+
*
182+
* @throws android.content.ActivityNotFoundException
183+
*
184+
* @see Activity#startActivity(Intent)
185+
* @see Activity#startActivityForResult(Intent, int)
186+
* @see Activity#startActivityFromChild
187+
*
188+
* {@hide}
189+
*/
190+
public ActivityResult execStartActivity(
191+
Context who, IBinder contextThread, IBinder token, Activity target,
192+
Intent intent, int requestCode, Bundle options) {
193+
IApplicationThread whoThread = (IApplicationThread) contextThread;
194+
Uri referrer = target != null ? target.onProvideReferrer() : null;
195+
if (referrer != null) {
196+
intent.putExtra(Intent.EXTRA_REFERRER, referrer);
197+
}
198+
if (mActivityMonitors != null) {
199+
synchronized (mSync) {
200+
final int N = mActivityMonitors.size();
201+
for (int i=0; i<N; i++) {
202+
final ActivityMonitor am = mActivityMonitors.get(i);
203+
if (am.match(who, null, intent)) {
204+
am.mHits++;
205+
if (am.isBlocking()) {
206+
return requestCode >= 0 ? am.getResult() : null;
207+
}
208+
break;
209+
}
210+
}
211+
}
212+
}
213+
try {
214+
intent.migrateExtraStreamToClipData();
215+
intent.prepareToLeaveProcess();
216+
// 通过注释然后再结合代码一看我们就知道这应该就是分发到系统activity manager的过程
217+
int result = ActivityManagerNative.getDefault()
218+
.startActivity(whoThread, who.getBasePackageName(), intent,
219+
intent.resolveTypeIfNeeded(who.getContentResolver()),
220+
token, target != null ? target.mEmbeddedID : null,
221+
requestCode, 0, null, options);
222+
checkStartActivityResult(result, intent);
223+
} catch (RemoteException e) {
224+
throw new RuntimeException("Failure from system", e);
225+
}
226+
return null;
227+
}
228+
```
229+
那就直接看下`ActivityManagerNative.getDefault().startActivity()`方法,看之前我们先看看`ActivityManagerNative.getDefault()`是什么鬼:
230+
```java
231+
/**
232+
* Retrieve the system's default/global activity manager.
233+
*/
234+
static public IActivityManager getDefault() {
235+
return gDefault.get();
236+
}
237+
```
238+
注释说的明白的就是拿到系统默认/全局的`activity manager`,通过名字也能看出来`IActivityManager`是个接口,那就继续看`IActivityManager.startActivity()`方法吧:
239+
```java
240+
public int startActivity(IApplicationThread caller, String callingPackage, Intent intent,
241+
String resolvedType, IBinder resultTo, String resultWho, int requestCode, int flags,
242+
ProfilerInfo profilerInfo, Bundle options) throws RemoteException;
243+
```
244+
这里就顺便看一下`IActivityManager`接口是神马鬼:
245+
```
246+
/**
247+
* System private API for talking with the activity manager service. This
248+
* provides calls from the application back to the activity manager.
249+
*
250+
* {@hide}
251+
*/
252+
public interface IActivityManager extends IInterface {
253+
...
254+
}
255+
```
256+
但是看到这里我不知道怎么继续往下分析了啊,既然是接口我们要找到实现类啊,又是通过`ActivityManagerNative.getDefault()`得到的`IActivityManager`实例,
257+
所以这里我们再看下`ActivityManagerNative`类。
258+
```java
259+
/** {@hide} */
260+
public abstract class ActivityManagerNative extends Binder implements IActivityManager {
261+
...
262+
}
263+
```
264+
啊! 隐藏的,连个注释也没有,我拖动了下这个类一看`5992`行,不知道从哪下手了,还能从哪下手啊,当然是从`ActivityManagerNative.getDefault()`方法啊
265+
```java
266+
public abstract class ActivityManagerNative extends Binder implements IActivityManager {
267+
268+
// 继承Binder接口,而且asInterFace方法,我好想明白了点什么
269+
/**
270+
* Cast a Binder object into an activity manager interface, generating
271+
* a proxy if needed.
272+
*/
273+
static public IActivityManager asInterface(IBinder obj) {
274+
if (obj == null) {
275+
return null;
276+
}
277+
IActivityManager in =
278+
(IActivityManager)obj.queryLocalInterface(descriptor);
279+
if (in != null) {
280+
return in;
281+
}
282+
283+
return new ActivityManagerProxy(obj);
284+
}
285+
286+
/**
287+
* Retrieve the system's default/global activity manager.
288+
*/
289+
static public IActivityManager getDefault() {
290+
// 使用了getDefaule的get方法
291+
return gDefault.get();
292+
}
293+
....
294+
}
295+
```
296+
继续看:  
297+
```java
298+
private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>() {
299+
protected IActivityManager create() {
300+
// 进程间通信了
301+
IBinder b = ServiceManager.getService("activity");
302+
if (false) {
303+
Log.v("ActivityManager", "default service binder = " + b);
304+
}
305+
// 看到了吗?用到了刚才我们说的asInterface方法
306+
IActivityManager am = asInterface(b);
307+
if (false) {
308+
Log.v("ActivityManager", "default service = " + am);
309+
}
310+
return am;
311+
}
312+
};
313+
```
314+
好了,我们再看下`asInterface()`方法:    
315+
```java
316+
static public IActivityManager asInterface(IBinder obj) {
317+
if (obj == null) {
318+
return null;
319+
}
320+
IActivityManager in =
321+
(IActivityManager)obj.queryLocalInterface(descriptor);
322+
if (in != null) {
323+
return in;
324+
}
325+
// 在这里
326+
return new ActivityManagerProxy(obj);
327+
}
328+
```
329+
终于找到了其实就是`ActivityManagerProxy`类,刚才我们找到`IActivityManager`接口的`startActivity()` 方法,现在终于找到了在这里使用的是`IActivityManager`接口实现类的
330+
`ActivityManagerProxy`类,我们来看一下该类实现的`startActivity()`方法:
331+
```java
332+
class ActivityManagerProxy implements IActivityManager
333+
{
334+
public ActivityManagerProxy(IBinder remote)
335+
{
336+
mRemote = remote;
337+
}
338+
339+
public IBinder asBinder()
340+
{
341+
return mRemote;
342+
}
343+
public int startActivity(IApplicationThread caller, String callingPackage, Intent intent,
344+
String resolvedType, IBinder resultTo, String resultWho, int requestCode,
345+
int startFlags, ProfilerInfo profilerInfo, Bundle options) throws RemoteException {
346+
Parcel data = Parcel.obtain();
347+
Parcel reply = Parcel.obtain();
348+
data.writeInterfaceToken(IActivityManager.descriptor);
349+
data.writeStrongBinder(caller != null ? caller.asBinder() : null);
350+
data.writeString(callingPackage);
351+
intent.writeToParcel(data, 0);
352+
data.writeString(resolvedType);
353+
data.writeStrongBinder(resultTo);
354+
data.writeString(resultWho);
355+
data.writeInt(requestCode);
356+
data.writeInt(startFlags);
357+
if (profilerInfo != null) {
358+
data.writeInt(1);
359+
profilerInfo.writeToParcel(data, Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
360+
} else {
361+
data.writeInt(0);
362+
}
363+
if (options != null) {
364+
data.writeInt(1);
365+
options.writeToParcel(data, 0);
366+
} else {
367+
data.writeInt(0);
368+
}
369+
mRemote.transact(START_ACTIVITY_TRANSACTION, data, reply, 0);
370+
reply.readException();
371+
int result = reply.readInt();
372+
reply.recycle();
373+
data.recycle();
374+
return result;
375+
}
376+
...
377+
}
378+
```
379+
再继续我就不知道走到哪里了....
380+
381+
382+
---
383+
384+
- 邮箱 :charon.chui@gmail.com
385+
- Good Luck!

0 commit comments

Comments
 (0)