Android

界面显示_Activity启动_App流程

2018-02-27  本文已影响12人  gczxbb

App进程从主消息队列捕获LAUNCH_ACTIVITY消息,完成Activity启动过程。

启动流程

入口方法,ActivityThread#handleLaunchActivity。

private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent) {
     ...
    //WindowManagerGlobal 初始化
    WindowManagerGlobal.initialize();
    //第一步
    Activity a = performLaunchActivity(r, customIntent);
    if (a != null) {
        //第二步
        handleResumeActivity(r.token, false, r.isForward,
                    !r.activity.mFinished && !r.startsNotResumed);
        ...
    } else {
        try {
             //Activity对象未成功创建,告知AMS结束Activity的启动
             ActivityManagerNative.getDefault()
                    .finishActivity(r.token, Activity.RESULT_CANCELED, null, false);
        } catch (RemoteException ex) {
             // Ignore
        }
    }
}

主要工作分两步
1.performLaunchActivity

2.handleResumeActivity

App进程_Activity启动时序流程图如下: Activity启动App端时序图.png
第一步

创建Activity,Context、Application对象,attach方法将一些Ams传递参数赋值给Activity,生命周期onCreate与onStart方法执行。
ActivityThread#performLaunchActivity方法

private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
    ...
    ActivityClientRecord中封装的是AMS传来的信息
    //创建Activity实例 
    ComponentName component = r.intent.getComponent();
    java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
    activity = mInstrumentation.newActivity(cl, component.getClassName(), r.intent);
    ...
    //创建Application对象,赋值给Activity内部
    Application app = r.packageInfo.makeApplication(false, mInstrumentation);
    ...
    //创建Context对象,赋值给Activity内部
    Context appContext = createBaseContextForActivity(r, activity);
    //执行Activity的attach方法
    activity.attach(appContext, this, getInstrumentation(), r.token,
                        r.ident, app, r.intent, r.activityInfo, title, r.parent,
                        r.embeddedID, r.lastNonConfigurationInstances, config,
                        r.referrer, r.voiceInteractor);
    ...
    //触发生命周期方法onCreate
    mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);

    r.activity = activity;
    r.stopped = true;
    if (!r.activity.mFinished) {
        //触发生命周期方法onStart,stop标志设为false
        activity.performStart();
        r.stopped = false;
    }
    if (!r.activity.mFinished) {
        //触发Activity的onRestoreInstanceState方法
        mInstrumentation.callActivityOnRestoreInstanceState(activity,r.state,
                r.persistentState);
    }   
    ...
    if (!r.activity.mFinished) {
        //触发Activity的onPostCreate方法
        mInstrumentation.callActivityOnPostCreate(activity, r.state,r.persistentState);
    }
    //绑定token与ActivityClientRecord,Map数组<IBinder, ActivityClientRecord>
    mActivities.put(r.token, r);

    return activity
}
第二步

生命周期onResume执行,窗体与视图的绑定,界面显示到用户面前。
ActivityThread#handleResumeActivity方法

final void handleResumeActivity(IBinder token, boolean clearHide, 
        boolean isForward, boolean reallyResume) {
    ActivityClientRecord r = performResumeActivity(token, clearHide);
    if (r != null) {
        final Activity a = r.activity;
        ...
        if (r.window == null && !a.mFinished && willBeVisible) {
            //在attach()中已经为Activity创建了Window
            r.window = r.activity.getWindow();
            View decor = r.window.getDecorView();
             //此时DecorView不可见
            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 (a.mVisibleFromClient) {
                a.mWindowAdded = true;
                //绑定View
                wm.addView(decor, l);
            }
        } else if (!willBeVisible) {
            r.hideForNow = true;
        }

        if (!r.activity.mFinished && willBeVisible
                    && r.activity.mDecor != null && !r.hideForNow) {
            ...
            r.activity.mVisibleFromServer = true;
            mNumVisibleActivities++;
            if (r.activity.mVisibleFromClient) {
                //让DecorView可见,即调用DecorView的setVisibility(View.VISIBLE)
                r.activity.makeVisible();
            }
        }

        if (reallyResume) {
            try {
                ActivityManagerNative.getDefault().activityResumed(token);
            } catch (RemoteException ex) {
            }
        }
    }
}

Activity、Context与Application对象创建

创建Activity

ActivityClientRecord对象封装Ams传递的变量,根据ActivityClientRecord#intent提供的ComponentName组件类名,Instrumentation#newActivity方法通过newInstance实例化Activity对象。

Instrumentation#newActivity方法

public Activity newActivity(ClassLoader cl, String className,Intent intent)
                    throws InstantiationException, IllegalAccessException,
            ClassNotFoundException {
    return (Activity)cl.loadClass(className).newInstance();
}
创建Application

Application是全局对象,继承ContextWrapper,App中公用

LoadedApk#makeApplication方法负责创建,第一次创建成功后,保存在LoadedApk,触发Application#onCreate方法(仅一次),再次启动Activity组件时,返回LoadedApk中保存的Application对象。

LoadedApk#makeApplication方法

public Application makeApplication(boolean forceDefaultAppClass,
            Instrumentation instrumentation) {
    if (mApplication != null) {
        return mApplication;
    }
    Application app = null;
    ...
    try {
        java.lang.ClassLoader cl = getClassLoader();
        //创建App ContextImpl
        ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
        app = mActivityThread.mInstrumentation.newApplication(
                    cl, appClass, appContext);
        appContext.setOuterContext(app);
    } catch (Exception e) {
        ...       
    }
    ...
    mApplication = app;

    if (instrumentation != null) {
        try {
            //触发Application的onCreate方法
            instrumentation.callApplicationOnCreate(app);
        } catch (Exception e) {

        }
    }
    ...
    return app;
}
创建Application的ContextImpl

ContextImpl#createAppContext方法创建Application的ContextImpl。

将ContextImpl对象attach到Application内部。callApplicationOnCreate触发Applicaiton#onCreate方法,整个App进程仅执行一次。
注意,Service组件的ContextImpl也通过ContextImpl#createAppContext方法创建。
ContextImpl与Activity、Service、Application结构关系图如下所示。

ContextImpl与Activity、Service、Application结构关系图.png
创建Activity的ContextImpl

ContextImpl#createActivityContext方法创建Activity的ContextImpl。

ActivityThread#createBaseContextForActivity方法

private Context createBaseContextForActivity(ActivityClientRecord r, final 
        Activity activity) {
    ...
    //创建Activity ContextImpl
    ContextImpl appContext = ContextImpl.createActivityContext(
                this, r.packageInfo, displayId, r.overrideConfig);
    appContext.setOuterContext(activity);
    Context baseContext = appContext;
    ...
    return baseContext;
}

Activity继承装饰类ContextWrapper,Activity内部mBase即ContextImpl,通过attach方法初始化mBase。

系统中每个Activty组件都创建一个ContextImpl,实现Activity抽象方法具体功能。

attach方法

Activity#attach方法,负责将一些参数(包括Ams传递封装在ActivityClientRecord的参数)传递给Activity组件,同时创建窗体PhoneWindow窗体管理者WindowManagerImpl。Activity绑定的对象包括Context、ActivityThread、Instrumentation、Application、ActivityInfo、Intent、IBinder对象token等。
Activity#attach方法

final void attach(Context context, ActivityThread aThread,
            Instrumentation instr, IBinder token, int ident,
            Application application, Intent intent, ActivityInfo info,
            CharSequence title, Activity parent, String id,
            NonConfigurationInstances lastNonConfigurationInstances,
            Configuration config, String referrer, IVoiceInteractor voiceInteractor) {
    attachBaseContext(context);
    创造窗体对象
    mWindow = new PhoneWindow(this);
    mWindow.setCallback(this);
    ...
    //参数赋值给Activity
    mUiThread = Thread.currentThread();
    mMainThread = aThread;
    mInstrumentation = instr;
    mToken = token;
    mApplication = application;
    mIntent = intent;
    mComponent = intent.getComponent();
    mActivityInfo = info;
    mParent = parent;
    ...
    //创建Window内部的窗体管理者WindowManager
    mWindow.setWindowManager( (WindowManager)context.getSystemService(Context.WINDOW_SERVICE),
                mToken, mComponent.flattenToString(),
                (info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0);
    
    //WindowManager同时赋值给Activity对象
    mWindowManager = mWindow.getWindowManager();
}

PhoneWindow继承Window,WindowManager继承ViewManager接口,WindowManagerImpl是实现类,提供Window对视图的操作。
Window#setWindowManager方法

public void setWindowManager(WindowManager wm, IBinder appToken, String appName,
            boolean hardwareAccelerated) {
    mAppToken = appToken;
    mAppName = appName;
    ...
    mWindowManager =((WindowManagerImpl)wm).createLocalWindowManager(this);
}

Context#getSystemService方法获取的WindowManager是公用WindowManagerImpl,不管理任何窗体。WindowManager#createLocalWindowManager方法负责创建本地窗体管理者,参数传递将管理的窗体。

public WindowManagerImpl createLocalWindowManager(Window parentWindow) {
    //mDisplay是公用wm
    return new WindowManagerImpl(mDisplay, parentWindow);
}

窗体PhoneWindow有一个本地窗体管理者WindowManagerImpl,负责管理它。

WindowManagerImpl注册与获取

SystemServiceRegistry类的static代码块,多次调用registerService方法,注册多个服务。服务封装在CachedServiceFetcher,CachedServiceFetcher保存在静态HashMap。

private static final HashMap<Class<?>, String> SYSTEM_SERVICE_NAMES = 
        new HashMap<Class<?>, String>();
private static final HashMap<String, ServiceFetcher<?>> SYSTEM_SERVICE_FETCHERS = 
        new HashMap<String, ServiceFetcher<?>>();

SystemServiceRegistry#static代码块

registerService(Context.WINDOW_SERVICE, WindowManager.class,
      new CachedServiceFetcher<WindowManager>() {
    @Override
    public WindowManager createService(ContextImpl ctx) {
        return new WindowManagerImpl(ctx.getDisplay());
    }
});

SystemServiceRegistry#registerService方法

private static <T> void registerService(String serviceName, Class<T> serviceClass,
            ServiceFetcher<T> serviceFetcher) {
    SYSTEM_SERVICE_NAMES.put(serviceClass, serviceName);
    SYSTEM_SERVICE_FETCHERS.put(serviceName, serviceFetcher);
}

服务注册是将服务类与服务字符串,字符串与ServiceFetcher存入两个HashMap。

CachedServiceFetcher继承ServiceFetcher,将服务封装成CachedServiceFetcher。

ContextImpl#getSystemService获取服务时,触发SystemServiceRegistry#getSystemService方法,根据服务字符串在HashMap查找CachedServiceFetcher<T>
SystemServiceRegistry#getSystemService方法

public static Object getSystemService(ContextImpl ctx, String name) {
    ServiceFetcher<?> fetcher = SYSTEM_SERVICE_FETCHERS.get(name);
    return fetcher != null ? fetcher.getService(ctx) : null;
}

查找CachedServiceFetcher,触发CachedServiceFetcher#getService方法。
CachedServiceFetcher#getService方法

public final T getService(ContextImpl ctx) {
    final Object[] cache = ctx.mServiceCache;
    synchronized (cache) {
        Object service = cache[mCacheIndex];
        if (service == null) {
            service = createService(ctx);
            cache[mCacheIndex] = service;
        }
        return (T)service;
    }
}

根据mCacheIndex在ContxetImpl的mServiceCache服务缓存数组查找服务对象
mCacheIndex是服务注册时,保存在CachedServiceFetcher,注册顺序的索引,定值。若未找到,createService创建。

每一个服务的CachedServiceFetcher重写createService方法创建每一个特定的服务对象,window服务创建WindowManagerImpl对象。

创建成功并且插入mServiceCache数组,索引是mCacheIndex,数组大小与服务索引是static代码段创建CachedServiceFetcher对象的总数及顺序服务对象仅创建一个,存储在ContextImpl的服务缓存数组。

WindowManagerGlobal对象
WindowManagerImpl与WindowManagerGlobal关系图如下: WindowManagerImpl与WindowManagerGlobal关系图.png

在整个应用中,WindowManagerGlobal是单例,WindowManagerImpl的主要方法委派给WindowManagerGlobal实现。例如,WindowManagerImpl#addView方法,触发WindowManagerGlobal#addView方法,后面会介绍。

WindowManagerGlobal提供Wms、WindowSession代理对象。Wms服务代理是IWindowManager业务类型,Wms服务代理是单例。Session在system_server进程,sWindowSession是App进程端代理对象。
Wms#openSession方法

@Override
public IWindowSession openSession(IWindowSessionCallback callback, 
                  IInputMethodClient client,IInputContext inputContext) {
    Session session = new Session(this, callback, client, inputContext);
    return session;
}

总结:
attach方法
窗体与本地窗体管理者创建,真正视图管理委派给全局WindowManagerGlobal对象
Activity内部ContextImpl、ActivityThread、Application完成赋值初始化。

Activity生命周期onCreate、onStart和onResume

Activity生命周期:onCreate,onStart,onResume,onPause,onStop,onDestory。

Instrumentation#callActivityOnCreate方法

public void callActivityOnCreate(Activity activity, Bundle icicle,
            PersistableBundle persistentState) {
    prePerformCreate(activity);
    activity.performCreate(icicle, persistentState);
    postPerformCreate(activity);
}

Activity#performCreate触发onCreate方法,Activity#performStart触发onStart方法
performResumeActivity执行Activity#performResume,触发onResume方法
ActivityThread#performResumeActivity方法

public final ActivityClientRecord performResumeActivity(IBinder token,
            boolean clearHide) {
    //根据token在mActivities Map中获取ActivityClientRecord
    ActivityClientRecord r = mActivities.get(token);
    try {
        r.activity.onStateNotSaved();
        r.activity.mFragments.noteStateNotSaved();
        ...
        r.activity.performResume();
        ...
        r.paused = false;
        r.stopped = false;
        ...
    } catch (Exception e) {  
    }
}

Activity#performResume首先调用performRestart,在mStop标志位是true时才会触发onRestart方法,然后调用Instrumentation#callActivityOnResume,执行onResume。

final void performResume() {
    performRestart();
    ...
    mInstrumentation.callActivityOnResume(this);
    ....
}

注意:performRestart在mStop标志是true时才会执行,默认是false,当onStop方法执行后,mStop标志才会被设为true。

综上,启动Activity,生命周期方法依次onCreate、onStart、onResume

视图布局初始化

视图依赖窗体,Window窗体是View的容器,手机平台窗体是PhoneWindow。PhoneWindow内部类DecorView是View树形结构中的根视图,继承FrameLayout布局类。
PhoneWindow构造方法创建一个布局解析器LayoutInflater。

public PhoneWindow(Context context) {
    super(context);
    mLayoutInflater = LayoutInflater.from(context);
}

在Activity#onCreate方法,setContentView(int layoutResID)方法设置视图,传入布局的资源ID,调用PhoneWindow#setContentView方法,将布局资源ID代表的xml文件节点解析成View对象

private DecorView mDecor;根View
private ViewGroup mContentParent;//存放解析出外部的View
private ViewGroup mContentRoot;//mDecor的直接子View

PhoneWindow#setContentView方法

@Override
public void setContentView(int layoutResID) {
    if (mContentParent == null) {
        //初始化mDecor,创建mContentParent和mContentRoot
        installDecor();
    } else if (!hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
       mContentParent.removeAllViews();
    }

    if (hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
            final Scene newScene = Scene.getSceneForLayout(mContentParent, layoutResID,
                    getContext());
            transitionTo(newScene);
    } else {
            //解析资源ID的View加入到mContentParent的子View中去
            mLayoutInflater.inflate(layoutResID, mContentParent);
    }
    mContentParent.requestApplyInsets();
    final Callback cb = getCallback();
    if (cb != null && !isDestroyed()) {
        cb.onContentChanged();
    }
}

PhoneWindow#setContentView方法解析xml、创建DecorView、根据Window特性初始化特定的视图、增加视图到DecorView。
mContentRoot是DecorView子视图,根据Window不同特性Feature,系统在解析时,选择不同的布局资源layoutResource。
mContentRoot创建的代码段

View in = mLayoutInflater.inflate(layoutResource, null);
decor.addView(in, new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT));
mContentRoot = (ViewGroup) in;
...

这里选择最简单的一种screen_simple.xml布局资源文件

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true"
    android:orientation="vertical">
    <ViewStub android:id="@+id/action_mode_bar_stub"
              android:inflatedId="@+id/action_mode_bar"
              android:layout="@layout/action_mode_bar"
              android:layout_width="match_parent"
              android:layout_height="wrap_content"
              android:theme="?attr/actionBarTheme" />
    <FrameLayout
         android:id="@android:id/content"
         android:layout_width="match_parent"
         android:layout_height="match_parent"
         android:foregroundInsidePadding="false"
         android:foregroundGravity="fill_horizontal|top"
         android:foreground="?android:attr/windowContentOverlay" />
</LinearLayout>

mContentRoot是screen_simple.xml文件解析出来的,通过findViewById解析内部FrameLayout节点获取mContentParent,资源ID是com.android.internal.R.id.content

ViewGroup contentParent = (ViewGroup)findViewById(ID_ANDROID_CONTENT);

总结:
mContentRoot视图是根据Android_Sdk的布局资源文件解析获取的,mContentParent视图是mContentRoot其中一个子视图,FrameLayout类型,用于装载用户在onCreate方法传入的布局资源。另外,mContentRoot还有其他的子视图,如ActionBar,装载到ViewStub节点

DecorView视图的内部关系图如下所示 DecorView内部关系.png

通过Layout Inspector工具查看视图层级如下所示。

redView.png 红色框的content代表mContentParent结构的内容,绿色框的LinearLayout代表mContentRoot结构的内容。

onCreate方法完成了View层级布局初始化,未对视图进行测量、布局、绘制,因此,此时在屏幕上无法看到视图。

窗体与视图绑定

在ActivitThread#handleResumeActivity方法触发绑定,执行本地WindowManagerImpl#addView方法。
WindowManagerImpl#addView方法

@Override
public void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {
    applyDefaultToken(params);
    mGlobal.addView(view, params, mDisplay, mParentWindow);
}

委托给WindowManagerGlobal对象。
WindowManagerGlobal#addView方法

public void addView(View view, ViewGroup.LayoutParams params,
            Display display, Window parentWindow) {
    ...
    ViewRootImpl root;
    View panelParentView = null;

    //创建ViewRootImpl
    root = new ViewRootImpl(view.getContext(), display);
    view.setLayoutParams(wparams);
    mViews.add(view);
    mRoots.add(root);
    mParams.add(wparams);
    ...
    //调用ViewRootImpl的方法
    root.setView(view, wparams, panelParentView);
}

每个视图有一个ViewParent对象,顶层视图DecorView的ViewParent是ViewRootImpl,其他视图的ViewParent是父视图ViewGroup,ViewGroup实现ViewParent接口。

当父视图增加View节点时,在ViewGroup#addView方法,通过child.assignParent(this)将父视图ViewGroup设置成子视图的ViewParent对象。

public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {
    if (mView == null) {
        //设置根视图
        mView = view;
        ...
        //设置内部mWindowAttributes属性
        mWindowAttributes.copyFrom(attrs);
        ...
        //设置内部mAttachInfo
        mAttachInfo.mRootView = view;
        mAttachInfo.mScalingRequired = mTranslator != null;
        mAttachInfo.mApplicationScale =
                        mTranslator == null ? 1.0f : mTranslator.applicationScale;
        requestLayout();
        ...
        //告诉WMS
        res = mWindowSession.addToDisplay(mWindow, mSeq, mWindowAttributes,
                            getHostVisibility(), mDisplay.getDisplayId(),
                            mAttachInfo.mContentInsets, mAttachInfo.mStableInsets,
                            mAttachInfo.mOutsets, mInputChannel)
        ...
        //初始化InputChannel 
        if (mInputChannel != null) {
            if (mInputQueueCallback != null) {
                mInputQueue = new InputQueue();
                mInputQueueCallback.onInputQueueCreated(mInputQueue);
            }
            mInputEventReceiver = new WindowInputEventReceiver(mInputChannel,
                   Looper.myLooper());
         }
        //为DecorView分配父视图管理ViewRootImpl。
        view.assignParent(this);
        ...
        //初始化事件责任链
        InputStage viewPostImeStage = new ViewPostImeInputStage(mSyntheticInputStage);
        ...
        mFirstInputStage = nativePreImeStage;
        mFirstPostImeInputStage = earlyPostImeStage;
    }  
}

利用IWindowSession#addToDisplay访问Wms服务,触发Wms#addWindow方法。
IWindowSession#addToDisplay方法

@Override
public int addToDisplay(IWindow window, int seq, WindowManager.LayoutParams attrs,
            int viewVisibility, int displayId, Rect outContentInsets, Rect outStableInsets,
            Rect outOutsets, InputChannel outInputChannel) {
    return mService.addWindow(this, window, seq, attrs, viewVisibility, displayId,
                outContentInsets, outStableInsets, outOutsets, outInputChannel);
}

system_server进程,Wms如何提供addWindow服务、如何通过IWindow与App交互的知识专门写Wms时再详细分析。


任重而道远

上一篇下一篇

猜你喜欢

热点阅读