Activity的启动过程-源码分析
以下分析基于android 27版本,所有流程基于函数调用顺序说明
启动基本时序图如下:
文章图片
image.png main()
我们知道所有的程序都是main()函数开始的,应用程序也是一样的,安卓里面的启动main()函数就在ActivityThread里面,源码体现如下:(部分进行了省略,具体的可以自己到源码进行查看)
main()方法里面进行了主线程的准备,以及一些相关对象的初始化工作。
public static void main(String[] args) {//···以上省略,重点代码如下//主线程Looper准备Looper.prepareMainLooper();
//初始化ActivityThread对象ActivityThread thread = new ActivityThread();
//划重点!!将当前ApplicationThread信息添加到ActivityManager上thread.attach(false);
//···以下省略,重点代码如上}
另外,在ActivityThread里面有有一些成员变量是跟随ActivityThread的实例化进行创建的,以下展示部分:
//、、、final ApplicationThread mAppThread = new ApplicationThread();
final Looper mLooper = Looper.myLooper();
final H mH = new H();
//H继承于Handler,用于进行线程间通讯,主要进行Activity的一些生命周期的调用final ArrayMap mActivities = new ArrayMap<>();
//此对象用于保存Activity的一些相关信息ActivityClientRecord mNewActivities = null;
// Number of activities that are currently visible on-screen.int mNumVisibleActivities = 0;
//、、、
【Activity的启动过程-源码分析】ApplicationThread是ActivityThread的内部类,并且是IApplicationThread.Stub的实现类,所以我们可以知道,ApplicationThread是通过实现Binder机制对Activity的一些相关操作进行控制的,部分代码如下:
文章图片
image.png 可以看出里面很多的对Activity的相关操作的方法,而方法里面的操作则是通过sendMessage()的方式回调到H里面进行操作(H是Handler的实现类)。以下举例一个方法:
public final void schedulePauseActivity(IBinder token, boolean finished,
boolean userLeaving, int configChanges, boolean dontReport) {
int seq = getLifecycleSeq();
if (DEBUG_ORDER) Slog.d(TAG, "pauseActivity " + ActivityThread.this
+ " operation received seq: " + seq);
sendMessage(
finished ? H.PAUSE_ACTIVITY_FINISHING : H.PAUSE_ACTIVITY,
token,
(userLeaving ? USER_LEAVING : 0) | (dontReport ? DONT_REPORT : 0),
configChanges,
seq);
}
attach() 此方法的作用就是将实例化好的mAppThread与ActivityManager进行注册,主要过程如下:
private void attach(boolean system) {
//···以上省略,重点代码如下
android.ddm.DdmHandleAppName.setAppName("",
UserHandle.myUserId());
RuntimeInit.setApplicationObject(mAppThread.asBinder());
//下面这行代码是重点
final IActivityManager mgr = ActivityManager.getService();
try {
//下面这行代码也是重点
mgr.attachApplication(mAppThread);
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
//···以下省略,重点代码如上
}
mAppThread是ApplicationThread的对象实例。
ActivityManager.getService()会通过Binder机制获取到IActivityManager对象,获取代码如下:
使用单例模式,通过Binder机制获取到ActivityService的IBinder对象,再转换成ActivityManager的代理对象。
看懂以下代码需要有一定的Binder机制基础,activity的启动代码里面涉及了Handler原理,Binder机制等相关知识,需要对这些有一定了解。
/**
* @hide
*/
public static IActivityManager getService() {
return IActivityManagerSingleton.get();
}private static final Singleton IActivityManagerSingleton =
new Singleton() {
@Override
protected IActivityManager create() {
final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
final IActivityManager am = IActivityManager.Stub.asInterface(b);
return am;
}
};
=======
通过以上main()方法和attach()方法,主线程的相关准备工作就完成了,剩下的就是Activity的相关启动了,而相关方法就到了ApplicationThread里面了(通过Binder机制远程调用启动)
第一步就是执行启动方法:scheduleLaunchActivity:
// we use token to identify this activity without having to send the
// activity itself back to the activity manager. (matters more with ipc)
@Override
public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
ActivityInfo info, Configuration curConfig, Configuration overrideConfig,
CompatibilityInfo compatInfo, String referrer, IVoiceInteractor voiceInteractor,
int procState, Bundle state, PersistableBundle persistentState,
List pendingResults, List pendingNewIntents,
boolean notResumed, boolean isForward, ProfilerInfo profilerInfo) {
updateProcessState(procState, false);
ActivityClientRecord r = new ActivityClientRecord();
r.token = token;
r.ident = ident;
r.intent = intent;
r.referrer = referrer;
r.voiceInteractor = voiceInteractor;
r.activityInfo = info;
r.compatInfo = compatInfo;
r.state = state;
r.persistentState = persistentState;
r.pendingResults = pendingResults;
r.pendingIntents = pendingNewIntents;
r.startsNotResumed = notResumed;
r.isForward = isForward;
r.profilerInfo = profilerInfo;
r.overrideConfig = overrideConfig;
updatePendingConfiguration(curConfig);
sendMessage(H.LAUNCH_ACTIVITY, r);
}
里面可以看到实例化了一个ActivityClientRecord类,这个类的作用就是记录Activity的相关参数信息。然后将记录好的相关activity信息通过handMessage的形式发送到H(ActivityThread的内部类,是Handler的实现类)里面进行处理,相关处理方法如下:(H里面还有很多相关Activity的相关其他操作方法,可以到源码查看)
public void handleMessage(Message msg) {
//···以上省略,重点代码如下
case LAUNCH_ACTIVITY: {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
final ActivityClientRecord r = (ActivityClientRecord) msg.obj;
r.packageInfo = getPackageInfoNoCheck(
r.activityInfo.applicationInfo, r.compatInfo);
handleLaunchActivity(r, null, "LAUNCH_ACTIVITY");
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
} break;
//···以下省略,重点代码如上
}
我们知道H也是ActivityThread里面的内部类,可以看到H里面的分发方法最后又调用了ActivityThread里面的handleLaunchActivity方法:具体如下
private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) {
//···以上省略,重点代码如下
WindowManagerGlobal.initialize();
Activity a = performLaunchActivity(r, customIntent);
if (a != null) {
r.createdConfig = new Configuration(mConfiguration);
reportSizeConfigurations(r);
Bundle oldState = r.state;
handleResumeActivity(r.token, false, r.isForward,
!r.activity.mFinished && !r.startsNotResumed, r.lastProcessedSeq, reason);
if (!r.activity.mFinished && r.startsNotResumed) {
performPauseActivityIfNeeded(r, reason);
if (r.isPreHoneycomb()) {
r.state = oldState;
}
}
} else {
// If there was an error, for any reason, tell the activity manager to stop us.
try {
ActivityManager.getService().finishActivity(r.token, Activity.RESULT_CANCELED, null,Activity.DONT_FINISH_TASK_WITH_ACTIVITY);
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
}
}
以上方法主要对WindowManager进行了实例化,window的处理也是比较需要重要了解的,相关类继承图如下:
文章图片
image.png handleLaunchActivity也初始化了一个Activity对象,初始化Activity过程如下:(通过ClassLoader获取了Activity对象)
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
//···以上省略,重点代码如下
ContextImpl appContext = createBaseContextForActivity(r);
Activity activity = null;
try {
java.lang.ClassLoader cl = appContext.getClassLoader();
activity = mInstrumentation.newActivity(
cl, component.getClassName(), r.intent);
StrictMode.incrementExpectedActivityCount(activity.getClass());
r.intent.setExtrasClassLoader(cl);
r.intent.prepareToEnterProcess();
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);
}
}
//···以下省略,重点代码如上
}
以上基本完成了对Activity的创建以及启动的之前的基本准备工作,后续的就是对窗口做相关的添加布局的操作了。
布局的处理就到了handleResumeActivity里面了,相关代码如下:
final void handleResumeActivity(IBinder token,
boolean clearHide, boolean isForward, boolean reallyResume, int seq, String reason) {
ActivityClientRecord r = mActivities.get(token);
//···以上省略,重点代码如下
if (r.window == null && !a.mFinished && willBeVisible) {
r.window = r.activity.getWindow();
View decor = r.window.getDecorView();
decor.setVisibility(View.INVISIBLE);
ViewManager wm = a.getWindowManager();
WindowManager.LayoutParams l = r.window.getAttributes();
a.mDecor = decor;
l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
l.softInputMode |= forwardBit;
if (r.mPreserveWindow) {
a.mWindowAdded = true;
r.mPreserveWindow = false;
// Normally the ViewRoot sets up callbacks with the Activity
// in addView->ViewRootImpl#setView. If we are instead reusing
// the decor view we have to notify the view root that the
// callbacks may have changed.
ViewRootImpl impl = decor.getViewRootImpl();
if (impl != null) {
impl.notifyChildRebuilt();
}
}
if (a.mVisibleFromClient) {
if (!a.mWindowAdded) {
a.mWindowAdded = true;
wm.addView(decor, l);
} else {
// The activity will get a callback for this {@link LayoutParams} change
// earlier. However, at that time the decor will not be set (this is set
// in this method), so no action will be taken. This call ensures the
// callback occurs with the decor set.
a.onWindowAttributesChanged(l);
}
}
// If the window has already been added, but during resume
// we started another activity, then don't yet make the
// window visible.
} else if (!willBeVisible) {
if (localLOGV) Slog.v(
TAG, "Launch " + r + " mStartedActivity set");
r.hideForNow = true;
}
//···以下省略,重点代码如上
}
handleResumeActivity里面就是关于window的添加的具体流程了,相关方法调用过程如下:
文章图片
image.png
推荐阅读
- 热闹中的孤独
- JAVA(抽象类与接口的区别&重载与重写&内存泄漏)
- 放屁有这三个特征的,请注意啦!这说明你的身体毒素太多
- 一个人的旅行,三亚
- 布丽吉特,人生绝对的赢家
- 慢慢的美丽
- 尽力
- 一个小故事,我的思考。
- 家乡的那条小河
- 《真与假的困惑》???|《真与假的困惑》??? ——致良知是一种伟大的力量