android (三)、Activity工作原理
启动一个新的应用程序时,首先会调用startActivity来启动Activity,此时进程还没有创建,会fork一个新进程,并创建ActivityThread实例;
Activity的创建过程
android中Activity只是一个控制器,负责用户操作和View之间传递消息,Activity创建一个能让用户摆放UI的Window(setContentView)实例,但它本身并不是一个view,也不对UI做任何操作。
Window是一个顶级窗口类,它作为一种表现策略,通常当作view添加到Window Manager中,每个Activity实例都对应一个Window实例。Window只是一个抽象类,它的实现类为android.policy.PhoneWindow,是个相当重要的类。
通常启动一个Activity会调用startActivity()方法,startActivity方法内部通过一个名叫Instrumentation的类来启动Activity。
Instrumentation是应用程序管理Activity的工具类,他提供了控制了activity的全生命周期的方法,应用创建的时,会先创建Instrumentation 实例,Instrumentation通过调用execStartActivities来启动Activity 。
Activity创建步骤如下:
第一步:由Context发送创建信息到Instrumentation。
第二步:Instrumentation再转发信息到ActivityManagerService。
第三步:ActivityManagerService做好Activity的相关记录工作后,发送创建信息到ApplicationThread。
第四部:ActivityThread调用(Instrumentation)Activity的创建方法,并执行Activity的生命周期。
以上四部是简化过的framework和应用之间信息传递的过程,实际操作会很复杂。
execStartActivities的方法体如下
public void execStartActivities(Context who, IBinder contextThread,
1431 IBinder token, Activity target, Intent[] intents, Bundle options) {
1432 IApplicationThread whoThread = (IApplicationThread) contextThread;
1433 if (mActivityMonitors != null) {
1434 ····
1447 }
1448 try {
1449 ·····
1454 int result = ActivityManagerNative.getDefault()
1455 .startActivities(whoThread, intents, resolvedTypes, token, options);
1456 checkStartActivityResult(result, intents[0]);
1457 } catch (RemoteException e) {
1458 }
1459 }
这个方法中传入了一个IApplicationThread对象,IApplicationThread类是ActivityThread的内部类,因为它是Binder的子类,所以这个类的主要工作就是跨进程通信。 方法内部有这么一句ActivityManagerNative.getDefault()代码,返回的其实是ActivityManagerService实例。ActivityManagerService调用startActivity方法,ActivityManagerService做好Activity信息记录后,向IApplicationThread发送创建Activity对象的命令,IApplicationThread是ActivityThread对外通信的接口。
IApplicationThread收到ActivityManagerService的创建Activity的命令后,会通过Handler向ActivityThread转达创建消息,ActivityThread收到信息后调用自身的handleLaunchActivity()方法。
这个方法的主要作用就是创建Activity对象和Application对象,并且执行Activity的attach方法,还调用了Activity生命周期中的onCreate方法。handleLaunchActivity方法体的主要内容如下:
private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent) {
2233 Activity a = performLaunchActivity(r, customIntent);此方法内部调用了Activity的attach方法
2235 if (a != null) {
2236 r.createdConfig = new Configuration(mConfiguration);
2237 Bundle oldState = r.state;
2238 handleResumeActivity(r.token, false, r.isForward,
2239 !r.activity.mFinished && !r.startsNotResumed);
2293 }
Activity的attach方法主要工作就是创建Window和绑定WindowManger实例,还有一个Window.setCallback(),这个方法主要就是让Activity能够收到用户的触摸事件等。
mWindow = PolicyManager.makeNewWindow(this);
5191 mWindow.setCallback(this);
5192 mWindow.getLayoutInflater().setPrivateFactory(this);
5214 mWindow.setWindowManager(
5215 (WindowManager)context.getSystemService(Context.WINDOW_SERVICE),
5216 mToken, mComponent.flattenToString(),
5217 (info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0);
5218 if (mParent != null) {
5219 mWindow.setContainer(mParent.getWindow());
5220 }
5221 mWindowManager = mWindow.getWindowManager();
在Activity执行onCreate方法前已经已经创建了WindowManger,在oncreate中一般会调用setContentView方法,这样就完成了View的添加。
1948 public void setContentView(View view) {
1949 getWindow().setContentView(view);
1950 initActionBar();
1951 }
在执行完Activity的创建后,又执行了handleResumeActivity方法,该方法主要是将activity的DectorView添加到WindowMnager中,这个过程也就是把setContentView中的view显示到屏幕上的操作。
final void handleResumeActivity(IBinder token, boolean clearHide, boolean isForward,
2798 boolean reallyResume) {
2803 ActivityClientRecord r = performResumeActivity(token, clearHide);
2804
2805 if (r != null) {
2806 ···········
2827 if (r.window == null && !a.mFinished && willBeVisible) {
2828 r.window = r.activity.getWindow();
2829 View decor = r.window.getDecorView();
2830 decor.setVisibility(View.INVISIBLE);
2831 ViewManager wm = a.getWindowManager();
2832 WindowManager.LayoutParams l = r.window.getAttributes();
2833 a.mDecor = decor;
2834 l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
2835 l.softInputMode |= forwardBit;
2836 if (a.mVisibleFromClient) {
2837 a.mWindowAdded = true;
2838 wm.addView(decor, l);
2839 }
2895 // Tell the activity manager we have resumed.
2896 if (reallyResume) {
2897 try {
2898 ActivityManagerNative.getDefault().activityResumed(token);
2899 } catch (RemoteException ex) {
2900 }
2901
2904 ·····
2912 }