frameworks\base\core\java\android\app\Activity.java
frameworks\base\core\java\com\android\internal\policy\PhoneWindow.java
frameworks\base\core\java\com\android\internal\policy\DecorView.java
frameworks\base\core\java\android\view\WindowManagerImpl.java
frameworks\base\core\java\android\view\WindowManagerGlobal.java
frameworks\base\core\java\android\view\ViewRootImpl.java
一.简述
当我们通过点击Launcher图标的方式去启动一个应用,如果该应用首次启动的话,系统会为其创建进程,并且启动它的首个界面,对于Activity的启动,在Activity的启动流程分析中也详细介绍过了,但是对于Activity启动之后,是如何展示给我们用户看的,对于它的绘制渲染过程,请看以下分析
二.绘制加载流程
2.1. Activity.attach
[-> Activity.java]
final void attach(Context context,ActivityThread aThread,
Instrumentation instr, IBindertoken, int ident,
Application application, Intentintent, ActivityInfo info,
CharSequence title, Activityparent, String id,
NonConfigurationInstances lastNonConfigurationInstances,
Configuration config, Stringreferrer, IVoiceInteractor voiceInteractor,
Window window) {
attachBaseContext(context);
mFragments.attachHost(null /*parent*/);
//为应用程序创建属于它的窗口对象
mWindow = new PhoneWindow(this,window);
mWindow.setWindowControllerCallback(this);
//将当前Activity对象传入窗口对象,设置回调,以便Activity能够响应窗口事件
mWindow.setCallback(this);
mWindow.setOnWindowDismissedCallback(this);
mWindow.getLayoutInflater().setPrivateFactory(this);
if (info.softInputMode !=WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED) {
mWindow.setSoftInputMode(info.softInputMode);
}
if (info.uiOptions != 0) {
mWindow.setUiOptions(info.uiOptions);
}
mUiThread = Thread.currentThread();
mMainThread = aThread;
mInstrumentation = instr;
mToken = token;
mIdent = ident;
mApplication = application;
mIntent = intent;
mReferrer = referrer;
mComponent = intent.getComponent();
mActivityInfo = info;
mTitle = title;
mParent = parent;
mEmbeddedID = id;
mLastNonConfigurationInstances =lastNonConfigurationInstances;
if (voiceInteractor != null) {
if (lastNonConfigurationInstances!= null) {
mVoiceInteractor =lastNonConfigurationInstances.voiceInteractor;
} else {
mVoiceInteractor = newVoiceInteractor(voiceInteractor, this, this,
Looper.myLooper());
}
}
//设置当前窗口的管理
mWindow.setWindowManager(
(WindowManager)context.getSystemService(Context.WINDOW_SERVICE),
mToken,mComponent.flattenToString(),
(info.flags &ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0);
if (mParent != null) {
mWindow.setContainer(mParent.getWindow());
}
mWindowManager =mWindow.getWindowManager();
mCurrentConfig = config;
Activity的界面绘制皆依于这个方法,Activity的初始化过程,对于我们首次启动需要创建承载其运行的应用程序,它的窗口对象的创建也是在此过程中完成。
当我们编写自己的Activity的时候重写onCreate方法,在方法体内会写上setContentView方法
此时从代码中看得出来,我们所创建的window还有Activity的界面内容,都还是处于模糊状态,到这里不能真正明白什么是window什么是Activity的内容界面,以及他们之间的关系?
当我们执行Activity启动流程的时候,执行performLaunchActivity然后回调Activity的onCreate方法,进而执行setContentview
2.2. Activity. setContentView
[->Activity.java]
public void setContentView(@LayoutRes intlayoutResID) {
getWindow().setContentView(layoutResID);
initWindowDecorActionBar();
}
这里通过getWindow方法获取在attach方法中创建的PhoneWindow,并且调用其setContentView方法
2.3. PW. setContentView
[->PhoneWindow.java]
@Override
public void setContentView(int layoutResID){
// Note: FEATURE_CONTENT_TRANSITIONSmay be set in the process of installing the window
// decor, when theme attributes and thelike are crystalized. Do not check the feature
// before this happens.
if (mContentParent == null) {
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 {
mLayoutInflater.inflate(layoutResID, mContentParent);
}
mContentParent.requestApplyInsets();
final Callback cb = getCallback();
if (cb != null &&!isDestroyed()) {
cb.onContentChanged();
}
mContentParentExplicitlySet = true;
}
这里我们首次启动该Activity,所以mContentParent==null,调用installDecor
2.3. PW. installDecor
private void installDecor() {
mForceDecorInstall = false;
if (mDecor == null) {
mDecor = generateDecor(-1);
mDecor.setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS);
mDecor.setIsRootNamespace(true);
if (!mInvalidatePanelMenuPosted&& mInvalidatePanelMenuFeatures != 0) {
mDecor.postOnAnimation(mInvalidatePanelMenuRunnable);
}
} else {
mDecor.setWindow(this);
}
if (mContentParent == null) {
mContentParent = generateLayout(mDecor);
// Set up decor part of UI toignore fitsSystemWindows if appropriate.
mDecor.makeOptionalFitsSystemWindows();
final DecorContentParentdecorContentParent = (DecorContentParent) mDecor.findViewById(
R.id.decor_content_parent);
if (decorContentParent != null) {
mDecorContentParent =decorContentParent;
mDecorContentParent.setWindowCallback(getCallback());
if(mDecorContentParent.getTitle() == null) {
mDecorContentParent.setWindowTitle(mTitle);
}
final int localFeatures =getLocalFeatures();
for (int i = 0; i <FEATURE_MAX; i++) {
if ((localFeatures & (1<< i)) != 0) {
mDecorContentParent.initFeature(i);
}
}
mDecorContentParent.setUiOptions(mUiOptions);
if ((mResourcesSetFlags &FLAG_RESOURCE_SET_ICON) != 0 ||
(mIconRes != 0&& !mDecorContentParent.hasIcon())) {
mDecorContentParent.setIcon(mIconRes);
} else if ((mResourcesSetFlags& FLAG_RESOURCE_SET_ICON) == 0 &&
mIconRes == 0&& !mDecorContentParent.hasIcon()) {
mDecorContentParent.setIcon(
getContext().getPackageManager().getDefaultActivityIcon());
mResourcesSetFlags |=FLAG_RESOURCE_SET_ICON_FALLBACK;
}
if ((mResourcesSetFlags &FLAG_RESOURCE_SET_LOGO) != 0 ||
(mLogoRes != 0&& !mDecorContentParent.hasLogo())) {
mDecorContentParent.setLogo(mLogoRes);
}
// Invalidate if the panel menuhasn't been created before this.
// Panel menu invalidation isdeferred avoiding application onCreateOptionsMenu
// being called in the middleof onCreate or similar.
// A pending invalidation willtypically be resolved before the posted message
// would run normally in orderto satisfy instance state restoration.
PanelFeatureState st =getPanelState(FEATURE_OPTIONS_PANEL, false);
if (!isDestroyed() &&(st == null || st.menu == null) && !mIsStartingWindow) {
invalidatePanelMenu(FEATURE_ACTION_BAR);
}
} else {
mTitleView = (TextView)findViewById(R.id.title);
if (mTitleView != null) {
if ((getLocalFeatures()& (1 << FEATURE_NO_TITLE)) != 0) {
final ViewtitleContainer = findViewById(R.id.title_container);
if (titleContainer !=null) {
titleContainer.setVisibility(View.GONE);
} else {
mTitleView.setVisibility(View.GONE);
}
mContentParent.setForeground(null);
} else {
mTitleView.setText(mTitle);
}
}
}
if (mDecor.getBackground() == null&& mBackgroundFallbackResource != 0) {
mDecor.setBackgroundFallback(mBackgroundFallbackResource);
}
// Only inflate or create a newTransitionManager if the caller hasn't
// already set a custom one.
if(hasFeature(FEATURE_ACTIVITY_TRANSITIONS)) {
if (mTransitionManager == null){
final int transitionRes =getWindowStyle().getResourceId(
R.styleable.Window_windowContentTransitionManager,
0);
if (transitionRes != 0) {
finalTransitionInflater inflater = TransitionInflater.from(getContext());
mTransitionManager =inflater.inflateTransitionManager(transitionRes,
mContentParent);
} else {
mTransitionManager =new TransitionManager();
}
}
mEnterTransition =getTransition(mEnterTransition, null,
R.styleable.Window_windowEnterTransition);
mReturnTransition =getTransition(mReturnTransition, USE_DEFAULT_TRANSITION,
R.styleable.Window_windowReturnTransition);
mExitTransition =getTransition(mExitTransition, null,
R.styleable.Window_windowExitTransition);
mReenterTransition =getTransition(mReenterTransition, USE_DEFAULT_TRANSITION,
R.styleable.Window_windowReenterTransition);
mSharedElementEnterTransition =getTransition(mSharedElementEnterTransition, null,
R.styleable.Window_windowSharedElementEnterTransition);
mSharedElementReturnTransition= getTransition(mSharedElementReturnTransition,
USE_DEFAULT_TRANSITION,
R.styleable.Window_windowSharedElementReturnTransition);
mSharedElementExitTransition =getTransition(mSharedElementExitTransition, null,
R.styleable.Window_windowSharedElementExitTransition);
mSharedElementReenterTransition= getTransition(mSharedElementReenterTransition,
USE_DEFAULT_TRANSITION,
R.styleable.Window_windowSharedElementReenterTransition);
if (mAllowEnterTransitionOverlap== null) {
mAllowEnterTransitionOverlap = getWindowStyle().getBoolean(
R.styleable.Window_windowAllowEnterTransitionOverlap, true);
}
if (mAllowReturnTransitionOverlap== null) {
mAllowReturnTransitionOverlap = getWindowStyle().getBoolean(
R.styleable.Window_windowAllowReturnTransitionOverlap, true);
}
if(mBackgroundFadeDurationMillis < 0) {
mBackgroundFadeDurationMillis = getWindowStyle().getInteger(
R.styleable.Window_windowTransitionBackgroundFadeDuration,
DEFAULT_BACKGROUND_FADE_DURATION_MS);
}
if (mSharedElementsUseOverlay== null) {
mSharedElementsUseOverlay =getWindowStyle().getBoolean(
R.styleable.Window_windowSharedElementsUseOverlay, true);
}
}
}
}
- 调用generateDecor方法生成DecorView,对于这个Decorview,就是就是window中最*view,它包含了window中所有的view这里对于DecorView在补充中做了详细的解释
- 调用generateLayout为mContentParent赋值
2.4. PW. generateDecor
[->PhoneWindow.java]
protected DecorView generateDecor(intfeatureId) {
// System process doesn't haveapplication context and in that case we need to directly use
// the context we have. Otherwise wewant the application context, so we don't cling to the
// activity.
Context context;
if (mUseDecorContext) {
Context applicationContext =getContext().getApplicationContext();
if (applicationContext == null) {
context = getContext();
} else {
context = newDecorContext(applicationContext, getContext().getResources());
if (mTheme != -1) {
context.setTheme(mTheme);
}
}
} else {
context = getContext();
}
return new DecorView(context,featureId, this, getAttributes());
}
创建了一个DecorView
2.5. PW. generateLayout
[->PhoneWindow.java]
generateLayout的工作主要可分为:
- 设置窗口的风格Feature,
- 设置标题栏
- 找到id为content的view并且返回赋值给mContentParent
当珍执行到这里的时候我们Activity的界面就算是绘制完成了,这里面有几个比较重要的变量,mWindow(Phonewindow),mDecor(DecorView),mContentParent(ViewGroup)
当系统为了显示Activity界面做足了准备之后,并且Activity的启动也到了handleResumeActivity这一步,这里就是要让Activity界面展示在手机的屏幕上,其中执行了这么一串代码r.activity.makeVisible(),进入流程2.6
2.6. Activity. makeVisible
[-> Activity.java]
void makeVisible() {
if (!mWindowAdded) {
ViewManager wm =getWindowManager();
wm.addView(mDecor,getWindow().getAttributes());
mWindowAdded = true;
}
mDecor.setVisibility(View.VISIBLE);
这里wm.addView调用的就是WindowManagerImpl的addView
2.7. WMI.addView
[->WindowManagerImpl.java]
public void addView(@NonNull View view,@NonNull ViewGroup.LayoutParams params) {
android.util.SeempLog.record_vg_layout(383,params);
applyDefaultToken(params);
mGlobal.addView(view, params,mContext.getDisplay(), mParentWindow);
mGlobal就是WindowManagerGlobal的对象
2.8. WMG. addView
[->WindowManagerGlobal.java]
public void addView(View view,ViewGroup.LayoutParams params,
Display display, WindowparentWindow) {
//获取窗口的参数
final WindowManager.LayoutParamswparams = (WindowManager.LayoutParams) params;
if (parentWindow != null) {
parentWindow.adjustLayoutParamsForSubWindow(wparams);
} else {
//获取上下文
final Context context =view.getContext();
if (context != null
&&(context.getApplicationInfo().flags
&ApplicationInfo.FLAG_HARDWARE_ACCELERATED) != 0) {
wparams.flags |=WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
}
}
ViewRootImpl root;
View panelParentView = null;
synchronized (mLock) {
// Start watching for systemproperty changes.
if (mSystemPropertyUpdater == null){
mSystemPropertyUpdater = newRunnable() {
@Override public void run(){
synchronized (mLock) {
for (int i =mRoots.size() - 1; i >= 0; --i) {
mRoots.get(i).loadSystemProperties();
}
}
}
};
SystemProperties.addChangeCallback(mSystemPropertyUpdater);
}
int index = findViewLocked(view,false);
if (index >= 0) {
if (mDyingViews.contains(view)){
// Don't wait for MSG_DIEto make it's way through root's queue.
mRoots.get(index).doDie();
} else {
throw newIllegalStateException("View " + view
+ " hasalready been added to the window manager.");
}
// The previous removeView()had not completed executing. Now it has.
}
// If this is a panel window, thenfind the window it is being
// attached to for futurereference.
if (wparams.type >=WindowManager.LayoutParams.FIRST_SUB_WINDOW &&
wparams.type <=WindowManager.LayoutParams.LAST_SUB_WINDOW) {
final int count =mViews.size();
for (int i = 0; i < count;i++) {
if(mRoots.get(i).mWindow.asBinder() == wparams.token) {
panelParentView =mViews.get(i);
}
}
}
root = newViewRootImpl(view.getContext(), display);
view.setLayoutParams(wparams);
mViews.add(view);
mRoots.add(root);
mParams.add(wparams);
}
// do this last because it fires offmessages to start doing things
try {
root.setView(view, wparams,panelParentView);
} catch (RuntimeException e) {
// BadTokenException orInvalidDisplayException, clean up.
synchronized (mLock) {
final int index =findViewLocked(view, false);
if (index >= 0) {
removeViewLocked(index,true);
}
}
throw e;
}
这里需要强调的是每一个App对应一个WMG,是App中全局的窗口管理模块,我们在Activity启动流程2.19中的AT.handleLaunchActivity中进行了初始化,其中WMG中有三个比较重要的数组对象(这三个对象随WMG初始化初始化):
- ArrayList<View> mViews = new ArrayList<View>();这个负责保存mDecor
- ArrayList<ViewRootImpl> mRoots = new ArrayList<ViewRootImpl>();这个用来保存ViewRootImpl用来关联View和ViewManager
- ArrayList<WindowManager.LayoutParams> mParams = new ArrayList<WindowManager.LayoutParams>();这个用来用来保存布局的属性
WMG的addview方法还创建了一个相当重要的成员就是ViewRootImpl
2.8.1 VRI. ViewRootImpl
[->ViewRootImpl.java]
public ViewRootImpl(Context context,Display display) {
mContext = context;
mWindowSession =WindowManagerGlobal.getWindowSession();
mDisplay = display;
mBasePackageName =context.getBasePackageName();
mThread = Thread.currentThread();
mLocation = new WindowLeaked(null);
mLocation.fillInStackTrace();
mWidth = -1;
mHeight = -1;
mDirty = new Rect();
mTempRect = new Rect();
mVisRect = new Rect();
mWinFrame = new Rect();//当前窗口的位置以及尺寸的描述,
mWindow = new W(this);// 继承于IWindow.Stub的W对象;
mTargetSdkVersion =context.getApplicationInfo().targetSdkVersion;
mViewVisibility = View.GONE;
mTransparentRegion = new Region();
mPreviousTransparentRegion = new Region();
mFirst = true; // true for the firsttime the view is added
mAdded = false;
mAttachInfo = newView.AttachInfo(mWindowSession, mWindow, display, this, mHandler, this);
mAccessibilityManager =AccessibilityManager.getInstance(context);
mAccessibilityInteractionConnectionManager =
newAccessibilityInteractionConnectionManager();
mAccessibilityManager.addAccessibilityStateChangeListener(
mAccessibilityInteractionConnectionManager);
mHighContrastTextManager = newHighContrastTextManager();
mAccessibilityManager.addHighTextContrastStateChangeListener(
mHighContrastTextManager);
mViewConfiguration =ViewConfiguration.get(context);
mDensity =context.getResources().getDisplayMetrics().densityDpi;
mNoncompatDensity =context.getResources().getDisplayMetrics().noncompatDensityDpi;
mFallbackEventHandler = new PhoneFallbackEventHandler(context);
mChoreographer = Choreographer.getInstance();//绘制相关的对象
mDisplayManager =(DisplayManager)context.getSystemService(Context.DISPLAY_SERVICE);
loadSystemProperties();
}
- 通过WMG获取一个mWindowSession,这个是用来与WMS通信的的代理
- mThread = Thread.currentThread();这里保存当前线程到VRI中,个人认为就是UI主线程
2.9. VRI. setView
[->ViewRootImpl.java]
VRI中就属setView和构造方法最重要,构造函数负责初始化所需要的各个成员,setView则负责创建窗口,建立输入事件接收的通道,并且请求WMS进行View绘制工作
- 保存View
- 创建InputChannel
- 调用requestLayout
- 调用mWindowSession.addToDisplay,就是最终调用的就是WMS的addWindow方法
2.9.1 WMS. addWindow
[-> WindowManagerService.java]
public intaddWindow(Session session, IWindow client, int seq,
WindowManager.LayoutParams attrs,int viewVisibility, int displayId,
Rect outContentInsets, RectoutStableInsets, Rect outOutsets,
InputChannel outInputChannel) {
...
//创建WindowState
WindowStatewin = new WindowState(this, session, client,token,
attachedWindow, appOp[0], seq,attrs, viewVisibility, displayContent);
if (outInputChannel != null &&(attrs.inputFeatures
&WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL) == 0) {
//根据WindowState的HashCode以及title来生成InputChannel名称
String name =win.makeInputChannelName();
//创建一对InputChannel
InputChannel[] inputChannels = InputChannel.openInputChannelPair(name);
//将socket服务端保存到WindowState的mInputChannel
win.setInputChannel(inputChannels[0]);
//socket客户端传递给outInputChannel
inputChannels[1].transferTo(outInputChannel);
//利用socket服务端作为参数
mInputManager.registerInputChannel(win.mInputChannel,win.mInputWindowHandle);
}
...
boolean focusChanged = false;
if (win.canReceiveKeys()) {
//新添加window能接收按下操作,则更新聚焦窗口。
focusChanged =updateFocusedWindowLocked(UPDATE_FOCUS_WILL_ASSIGN_LAYERS,
false /*updateInputWindows*/);
}
...
if (focusChanged) {
mInputMonitor.setInputFocusLw(mCurrentFocus, false/*updateInputWindows*/);
}
//设置当前聚焦窗口
mInputMonitor.updateInputWindowsLw(false/*force*/);
}
inputChannels数组:
- inputChannels[0]所对应的InputChannel名称的后缀为(server);
- inputChannels[1]所对应的InputChannel名称的后缀为(client);
其中:
- 服务端inputChannels[0]保存到WindowState的mInputChannel;
- 客户端inputChannels[1]传递给outInputChannel,最终传递给ViewRootImpl的mInputChannel;
2.9.2 InputChannel.openInputChannelPair
[-> InputChannel.java]
public static InputChannel[]openInputChannelPair(String name) {
if (name == null) {
throw newIllegalArgumentException("name must not be null");
}
if (DEBUG) {
Slog.d(TAG, "Opening inputchannel pair '" + name + "'");
}
returnnativeOpenInputChannelPair(name);
}
[->android_view_InputChannel.cpp]
staticjobjectArray android_view_InputChannel_nativeOpenInputChannelPair(JNIEnv* env,
jclass clazz, jstring nameObj) {
const char* nameChars =env->GetStringUTFChars(nameObj, NULL);
String8 name(nameChars);
env->ReleaseStringUTFChars(nameObj,nameChars);
sp<InputChannel> serverChannel;
sp<InputChannel> clientChannel;
status_t result = InputChannel::openInputChannelPair(name, serverChannel, clientChannel);
if (result) {
String8 message;
message.appendFormat("Could notopen input channel pair. status=%d", result);
jniThrowRuntimeException(env,message.string());
return NULL;
}
jobjectArray channelPair =env->NewObjectArray(2, gInputChannelClassInfo.clazz, NULL);
if (env->ExceptionCheck()) {
return NULL;
}
jobject serverChannelObj = android_view_InputChannel_createInputChannel(env,
new NativeInputChannel(serverChannel));//将Native的InputChannel转化换成java层
if (env->ExceptionCheck()) {
return NULL;
}
jobject clientChannelObj = android_view_InputChannel_createInputChannel(env,
newNativeInputChannel(clientChannel));
if (env->ExceptionCheck()) {
return NULL;
}
env->SetObjectArrayElement(channelPair,0, serverChannelObj);
env->SetObjectArrayElement(channelPair,1, clientChannelObj);
return channelPair;
}
这里需要说明的是gInputChannelClassInfo,在android_view_InputChannel.cpp已经说明jclass clazz= FindClassOrDie(env, "android/view/InputChannel");意思就是java的类,所以这里
- gInputChannelClassInfo.mPtr InputChannel的成员变量mPtr
- gInputChannelClassInfo.clazz指Java层的InputChannel类
- gInputChannelClassInfo.ctor constructor的缩写指Java层的InputChannel构造方法
因此这里所创建的channelPair数组就是java层的数组
我们再来看看status_t result =InputChannel::openInputChannelPair(name, serverChannel, clientChannel);做了什么事情
[-> InputTransport.cpp]
status_tInputChannel::openInputChannelPair(const String8& name,
sp<InputChannel>&outServerChannel, sp<InputChannel>& outClientChannel) {
int sockets[2];
if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0,sockets)) {
...
return result;
}
int bufferSize = SOCKET_BUFFER_SIZE;
setsockopt(sockets[0], SOL_SOCKET,SO_SNDBUF, &bufferSize, sizeof(bufferSize));
setsockopt(sockets[0], SOL_SOCKET,SO_RCVBUF, &bufferSize, sizeof(bufferSize));
setsockopt(sockets[1], SOL_SOCKET,SO_SNDBUF, &bufferSize, sizeof(bufferSize));
setsockopt(sockets[1], SOL_SOCKET,SO_RCVBUF, &bufferSize, sizeof(bufferSize));
String8 serverChannelName = name;
serverChannelName.append("(server)");
outServerChannel = newInputChannel(serverChannelName, sockets[0]);
String8 clientChannelName = name;
clientChannelName.append("(client)");
outClientChannel = newInputChannel(clientChannelName, sockets[1]);
return OK;
}
到这里还是很混乱,我们理一下,InputChannel是为了能够接受Input事件用的,当我们通过调用InputChannel.openInputChannelPair,创建了一对InputChannel,当然这是调用的Native方法创建的,从代码中看InputTransport.cpp这里的openInputChannelPair算是真正创建InputChannel的地方了。因此到这里一对Native层InputChannel对象完了
- sockets[0]所对应的InputChannel名称的后缀为(server);
- sockets[1]所对应的InputChannel名称的后缀为(client)
回到WMS. addWindow方法中
//将socket服务端保存到WindowState的mInputChannel
win.setInputChannel(inputChannels[0]);
//socket客户端传递给outInputChannel
inputChannels[1].transferTo(outInputChannel);
//利用socket服务端作为参数
mInputManager.registerInputChannel(win.mInputChannel,win.mInputWindowHandle);
经过一系列的调用之后,我们创建好了InputChannel,然后将server端保存到SystemServer中WindowState的mInputChannel中去,然后让InputDispatcher监听服务端,便于时间分发,将客户端放到Ui线程的VRI中创建的mInputChannel中去,然后Ui线程就从这个客户端中获取Input事件
2.10. VRI. requestLayout
[->ViewRootImpl.java]
这里就是涉及到Activity界面的详细的绘制,这里会检查线程,如果不是UI线程则报错,然后通过mChoreographer异步处理界面绘制操作,所以说界面的详细的绘制过程在子线程中执行的,计算组件大小,计算位置,绘制组件……..
三.总结
本文大致的介绍了Activity的绘制过程,因为实际运用中,Activity和Input事件交互较多,所以侧重分析了Activity怎么能够接受到用户的按键事件的,主要通过InputChannel,对于他是怎么通过InputChannel接受事件的,还需要继续分析Android中的Input系统。
3.1. 何为DecorView?
这里引用源码中的解释This is thetop-level view of the window, containing the window décor
3.2. 为何用DecorView?
3.3. 如何用DecorView?