1.ãAndroidãWindow/DecorView/ViewRootImpl
2.Android 14 HWUI 源码研究 View Canvas RenderThread ViewRootImpl skia
3.纯粹çè°è°android.R.id.content
4.❤️ Android 源码解读-从setContentView深入了解 Window|Activity|View❤️
5.android acitivyåwindowçåºå«
ãAndroidãWindow/DecorView/ViewRootImpl
æ ¹æ® Activityå¯å¨æµç¨ ï¼å½æµç¨è¿è¡å° ActivityThread.performLaunchActivity çæ¶åï¼ä¼å建Activityå®ä¾ï¼å¹¶è°ç¨å ¶ attach æ¹æ³ãå¨ attach æ¹æ³ä¸ï¼ä¼å建Windowçå®ä¾ãä¹å°±æ¯è¯´ï¼å¨Activityå®ä¾å建ä¹åï¼Window就已ç»å建好äºã
DecorViewå¨ç¬¬ä¸æ¬¡è°ç¨ Window.getDecorView çæ¶å被å建ãPhoneWindowç±»ç getDecorView æ¹æ³å®ç°å¦ä¸ï¼
ä¸è¬æ åµä¸ï¼å¨ onCreate åè°ä¸è°ç¨äº setContentView æ¹æ³ï¼DecorView就被åå§åäºã
è°ç¨é¾ä¸ºï¼
AppcompatActivity.setContentView ->
AppCompatDelegateImpl.setContentView ->
AppCompatDelegateImpl.ensureSubDecor ->
AppCompatDelegateImpl.createSubDecor ->
PhoneWindow.getDecorView ->
PhoneWindow.installDecor
æç»ï¼å¨ PhoneWindow.installDecor æ¹æ³ä¸ï¼DecorView被åå§åï¼
å¦å¤ï¼å¦æä¸è°ç¨ setContentView ï¼DecorViewåæ ·ä¹ä¼å¨ Activity.performCreate æ¹æ³ä¸è¾åçå°æ¹å建ã
ViewRootImplæ¯å¨WindowManagerGlobalç addView æ¹æ³ä¸è¢«åå§åçï¼å¹¶ä¸ä¹æ¯å¨è¿éä¸DecorViewè¿è¡ç»å®ï¼æ为DecorViewçparentãè°ç¨é¾å¯ä»¥è¿½æº¯å° ActivityThread.handleResumeActivity ä¸ï¼å¨ performResumeActivity è°ç¨ä¹åï¼ViewRootImpl被å建ã
ä¹å°±æ¯è¯´ï¼ViewRootImplæ¯å¨ onResume åè°ä¹åæè¿è¡åå§åçãè¿å¯ä»¥å¨ onResume ä¸æå° getWindow().getDecorView().getParent() è¯å®ã
å¨ äº ä¸ç¥éäºï¼ handleResumeActivity æ¹æ³æç»ä¼è°ç¨ WindowManagerGlobal.addView æ¹æ³ï¼å¨è¿é ViewRootImpl 被å建ï¼å¹¶ä¸éè¿ setView æ¹æ³ç»å®DecorViewï¼è¿äºé½åçå¨onResumeä¹åã
å¨ViewRootImplç setView æ¹æ³ä¸ï¼åä¼è°ç¨ requestLayout ï¼å¨è¿éå°±ä¼è¿è¡è¿ä¸ªViewæ ç第ä¸æ¬¡æµç»ãå ·ä½çæ¹å¼æ¯éè¿ scheduleTraversals æ¹æ³å Choreographer åéä¸ä¸ªé¢å®çæ¶æ¯ï¼å¹¶å¨ä¸ä¸æ¬¡å±å¹å·æ°çæ¶åè°ç¨ doTraversal â performTraversals æ¹æ³è¿è¡ViewTreeçæµéãå¸å±åç»å¶ã
ä»è¿ä¸ç¹æ们å¯ä»¥ç¥éï¼å¨Activityç onResume æä¹åççå½æµç¨ä¸è°ç¨Viewç getMesuredWidth æè getWidth é½ä¼è¿å0ï¼å 为è¿ä¸ªæ¶åè¿æ²¡æå¼å§æµéã
å½Viewæ è¿æ²¡æ被æµç»çæ¶åï¼View.postä¼å°è¿ä¸ªRunnableåéç»å é¨çä¸ä¸ªæ¶æ¯éåï¼ä¸æ¯ç³»ç»çæ¶æ¯éåï¼ãè¿ä¸ªæ¶æ¯éåä¸ä¿åçRunnableä¼å¨ä¸ä¸æ¬¡ performTraversals çæ¶å被æ§è¡ï¼è°ç¨é¾ä¸ºï¼
ViewRootImpl.performTraversals â
DecorView.dispatchAttachedToWindow â
... â
View.dispatchAttachedToWindow â
executeActions
æç»å¨ executeActions æ¹æ³ä¸ï¼Runnable对象被åéç»ViewRootImplçå é¨Handleræ§è¡ãä¹å°±æ¯è¯´ï¼å½è¿ä¸ªRunnable被æ§è¡çæ¶åï¼å·²ç»è³å°ç»è¿ä¸æ¬¡æµç»äºï¼æ以å¯ä»¥æ£ç¡®çè·åå°Viewç宽é«ï¼ä¹è¯´æäºä¸ºä»ä¹éè¿ View.post åéçRunnableä¼å¨ä¸»çº¿ä¸æ§è¡ã
å½Viewæ å·²ç»è¢«æµç»è¿äºï¼ View.post å°±ä¼ç´æ¥éè¿å é¨ç mHandler åéæ¶æ¯ï¼è¿ä¸ªHandleræ¯å¨attachçè¿ç¨ä¸è·ç AttachInfo ä¸èµ·ä¼ éç»Viewçï¼å®è´¨ä¸å°±æ¯ViewRootImplçå é¨Handlerã
Android HWUI 源码研究 View Canvas RenderThread ViewRootImpl skia
HUWUI是源码Android系统中负责应用可视化元素绘制的核心组件,其架构主要在C++层实现,源码从Java层接收View绘制信息,源码通过唯一的源码渲染线程使用skia技术完成渲染任务。整体上,源码从应用程序到UI线程,源码会员收益系统源码再到渲染线程,源码形成了清晰的源码层级关系。
HUWUI的源码构建主要包括三个核心类,它们分别是源码:RecordingCanvas、Canvas、源码RenderNode、源码RenderProxy、源码RenderThread、源码CanvasContext、源码IRenderPipeline。在Java层,新征服源码主要涉及两类Canvas,RecordingCanvas用于记录绘制指令,Canvas则是直接用于渲染。RecordingCanvas在构造时创建,而Canvas在调用时创建。这两个类在C++层分别对应SkiaRecordingCanvas和SkiaCanvas,后者直接引用SkCanvas。
在全局循环中,UI线程与渲染线程之间的协同操作至关重要。具体流程包括:新创建Activity后,附着到对应的PhoneWindow,然后调用PhoneWindow的setContentView方法,将View添加到DecorView作为子节点。接着,DecorView与ViewRootImpl对接,完成View的亨特国际源码更新与渲染。整个过程包含了measure、layout和draw等复杂子流程。
渲染线程创建与核心对象紧密关联,主要包括RenderProxy、RenderThread和DrawFrameTask。RenderProxy负责Java层信息的衔接,RenderThread作为进程唯一的渲染线程,持有DrawFrameTask和CanvasContext,完成一帧的绘制任务。指令记录流程的核心在于使用C++层的RecordingCanvas将View属性和绘制信息记录到DisplayList中,进而完成指令的渲染。
Surface、ANativeWindow、EGLSurface的创建流程在ViewRootImpl的performTraversals函数中初始化。ReliableSurface的封装和EGL与Skia环境的创建主要在RenderThread的requireGlContext函数中实现。从源码分析,discuz主页源码这一过程通常在三个地方调用。
View树与RenderNode树之间的协作关系明确,一个Application进程对应多个Activity,每个Activity与一个PhoneWindow绑定,PhoneWindow持有DecorView,DecorView对应一个ViewRootImpl,而ViewRootImpl与ThreadedRender模块对接。ThreadedRender与C++层的RenderProxy一一对应,RenderProxy持有关键对象,如RenderThread、CanvasContext、DrawFrameTask等。RenderThread是单例模式,进程唯一,负责一帧绘制的逻辑。
在RenderPipeline模块中,直播解析源码关键操作包括makeCurrent、draw和swapBuffers。Native Canvas在这一过程中扮演了桥梁角色,接收Java API调用,而RecordingCanvas完成Op记录,最终DisplayListData存储这些Op。
skia的核心资源主要在三个使用场景中发挥作用,具体细节需深入分析,这些资源对于实现高效、稳定的渲染效果至关重要。
纯粹çè°è°android.R.id.content
æ们å¨Activity.onCreateä¸æ§è¡setContentView,å ¶å®æ¯å¾Windowéé¢è¿è¡setContentView
注解1ï¼getWindow()è·åçæ¯mWindowï¼èmWindowå¨attachçæ¶åï¼åå§å为PhoneWindow
注解1ï¼å¦æmDecorä¹å°±æ¯DecorViewä¸åå¨ï¼å°±å建ä¸ä¸ªDecorViewï¼ä¹å°±æ¯æ§è¡æ³¨è§£2
注解3ï¼å¦æmContentParentä¸åå¨ï¼å°±ä½¿ç¨mDecorå建ä¸ä¸ªmContentParentï¼ä¹å°±æ¯æ§è¡æ³¨è§£4
注解1ï¼layoutå°±å®ä¹äºcontent id
注解2ï¼mDecoræèµæºæ件addViewå°æ¬èº«Viewä¸
注解3ï¼Window.javaä¸æå®ä¹åéID_ANDROID_CONTENT = com.android.internal.R.id.content;
æ们çfindViewById
注解1ï¼getDecorViewæ¯ä»DecorViewä¸è·åandroid.R.id.content
æ»ç»ï¼android.R.id.contentæ¥èªDecorView,ä½æ¯è¿ä¸ªä» ä» æ¯DecorViewçä¸ä¸ªåViewã
è¿éäºè§£å°å®æ¯åViewä¹åï¼å¾å¤äºæ å°±éè¦æ³¨æäºï¼ä¾å¦titleçå»é¤çç
❤️ Android 源码解读-从setContentView深入了解 Window|Activity|View❤️
Android系统中,Window、Activity、View之间的关系是紧密相连且相互作用的。了解这三者之间的关系,有助于深入理解Android应用的渲染和交互机制。
在Android中,通常在创建Activity时会调用`setContentView()`方法,以指定显示的布局资源。这个方法主要作用是将指定的布局添加到一个名为`DecorView`的容器中,并最终将其显示在屏幕上。这一过程涉及到多个组件的交互,下面分步骤解析。
在`Activity`类中,`setContentView()`方法调用`getWindow()`方法获取`Window`对象,而`Window`对象在`Activity`的`attach()`方法中被初始化。`Window`对象是一个抽象类,其默认实现为`PhoneWindow`,这是Android特定的窗口实现。
`PhoneWindow`在创建时会通过`setWindowManager()`方法与`WindowManager`进行关联。`WindowManager`是系统级组件,用于管理所有的窗口,包括窗口的创建、更新、删除等操作。`WindowManager`的管理最终由`WindowManagerService`(WMS)执行,这是一个运行在系统进程中的服务。
在`PhoneWindow`中,`installDecor()`方法会初始化`DecorView`和`mContentParent`。`mContentParent`是一个`ViewGroup`,用于存放`setContentView()`传入的布局。通过`mLayoutInflater`的`inflate()`方法,将指定的布局资源添加到`mContentParent`中。
`DecorView`是一个特殊的`FrameLayout`,包含了`mContentParent`。在完成布局的添加后,`DecorView`本身并没有直接与`Activity`建立联系,也没有被绘制到屏幕上显示。`DecorView`的绘制和显示发生在`Activity`的`onResume()`方法执行后,这时`Activity`中的内容才真正可见。
当`Activity`执行到`onCreate()`阶段时,其内容实际上并没有显示在屏幕上,直到执行到`onResume()`阶段,`Activity`的内容才被真正显示。这一过程涉及到`ActivityThread`中的`handleResumeActivity()`方法,该方法会调用`WindowManager`的`addView()`方法,将`DecorView`添加到`WindowManagerService`中,完成`DecorView`的绘制和显示。
`WindowManagerService`通过`addView()`方法将`DecorView`添加到显示队列中,并且在添加过程中,会创建关键的`ViewRootImpl`对象,进一步管理`DecorView`的布局、测量和绘制。`ViewRootImpl`会调用`mWindowSession`的`addToDisplay()`方法,将`DecorView`添加到真正的显示队列中。
`mWindowSession`是`WindowManagerGlobal`中的单例对象,其内部实际上是一个`IWindowSession`类型,通过`AIDL`接口与系统进程中的`Session`对象进行通信,最终实现`DecorView`的添加和显示。
通过`setView()`方法的实现,可以看到除了调用`IWindowSession`进行跨进程添加`View`之外,还会设置输入事件处理。当触屏事件发生时,这些事件首先通过驱动层的优化计算,通过`Socket`跨进程通知`Android Framework`层,最终触屏事件会通过输入管道传送到`DecorView`处理。
在`DecorView`内部,触屏事件会通过`onProcess`方法传递给`mView`,即`PhoneWindow`中的`DecorView`。最终,事件传递到`PhoneWindow`中的`View.java`实现的`dispatchPointerEvent()`方法,并调用`Window.Callback`的`dispatchTouchEvent(ev)`方法。对于`Activity`来说,`dispatchTouchEvent()`方法最终还是会调用`PhoneWindow`的`superDispatchTouchEvent()`,然后传递给`DecorView`的`superDispatchTouchEvent()`方法,完成事件的分发和处理。
综上所述,通过`setContentView()`的过程,我们可以清晰地看到`Activity`、`Window`、`View`之间的交互关系。整个过程主要由`PhoneWindow`组件主导,而`Activity`主要负责提供要显示的布局资源,其与屏幕的直接交互则通过`WindowManager`和`WindowManagerService`实现。
android acitivyåwindowçåºå«
ææ³å¤§å¤æ°äººï¼å¯¹äºè¿3个ä¸è¥¿çæ¦å¿µè½åºåï¼ä½æ¯å ·ä½åºå«å¨åªå´å¾é¾è¯´åºæ¥ã
æè¿éæ ¹æ®æ个人çç解æ¥è®²è®²æ个人对è¿3个æ¦å¿µçç解ãå½ç¶è¿é设计å°éç¨çäºä»¶çªå£æ¨¡åçéç¨GUI设计ï¼æè¿éå°±ä¸æç®è®²äºï¼çº¯ç²¹ä»æ¦å¿µä¸æ¥è¿è¡åºåã
Activityæ¯Androidåºç¨ç¨åºçè½½ä½ï¼å 许ç¨æ·å¨å ¶ä¸å建ä¸ä¸ªç¨æ·çé¢ï¼å¹¶æä¾ç¨æ·å¤çäºä»¶çAPIï¼å¦onKeyEvent, onTouchEventçã 并维æ¤åºç¨ç¨åºççå½å¨æï¼ç±äºandroidåºç¨ç¨åºçè¿è¡ç¯å¢åå ¶ä»æä½ç³»ç»ä¸åï¼androidçåºç¨ç¨åºæ¯è¿è¡å¨æ¡æ¶ä¹å ï¼æ以ä»çåºç¨ç¨åºä¸è½å½å½ä»è¿ç¨ç级å«å»èèï¼èæ´å¤æ¯ä»æ¦å¿µä¸å»èèãandroidåºç¨ç¨åºæ¯ç±å¤ä¸ªæ´»å¨å 积èæï¼èå个活å¨åæå ¶ç¬ç«ççå½å¨æï¼ãActivityæ¬èº«æ¯ä¸ªåºå¤§çè½½ä½ï¼å¯ä»¥ç解ææ¯åºç¨ç¨åºçè½½ä½ï¼å¦ææ¨æActivity,androidåºç¨å°æ æ³è¿è¡ãä¹å¯ä»¥ç解æandroidåºç¨ç¨åºçå ¥å£ãAcivityçå®ä¾å¯¹è±¡ç±ç³»ç»ç»´æ¤ãç³»ç»æå¡ActivityManagerè´è´£ç»´æ¤Activityçå®ä¾å¯¹è±¡ï¼å¹¶æ ¹æ®è¿è¡ç¶æç»´æ¤å ¶ç¶æä¿¡æ¯ã
ä½å¨ç¨æ·çº§å«ï¼ç¨åºåå¯è½æ ¹æ¿æç解æ为ä¸ä¸ªçé¢çè½½ä½ãä½ä» ä» æ¯ä¸ªè½½ä½ï¼å®æ¬èº«å¹¶ä¸è´è´£ä»»ä½ç»å¶ãActivityçå é¨å®ç°ï¼å®é ä¸æ¯èäºä¸ä¸ªWindow对象ãWindowæ¯ä¸ä¸ªæ½è±¡ç±»ï¼å®çå ·ä½æ¯å¨android_src_home/framework/policies/base/phone/com/android/internal/policy/implç®å½ä¸çPhoneWindow.javaã
å½æ们è°ç¨Acitivityç setContentViewæ¹æ³çæ¶åå®é ä¸æ¯è°ç¨çWindow对象çsetContentViewæ¹æ³ï¼æ以æ们å¯ä»¥çåºActivityä¸å ³äºçé¢çç»å¶å®é ä¸å ¨æ¯äº¤ç»Window对象æ¥åçãç»å¶ç±»å¾çè¯ï¼å¯ä»¥çåºActivityèåäºä¸ä¸ªWindow对象ã
ä¸é¢æ¯PhoneWindowä¸çsetContentViewæ¹æ³çå®ç°ï¼
@Override
public void setContentView(View view, ViewGroup.LayoutParams params) {
if (mContentParent == null) {
installDecor();
} else {
mContentParent.removeAllViews();
}
mContentParent.addView(view, params);
final Callback cb = getCallback();
if (cb != null) {
cb.onContentChanged();
}
}
Windowå é¨é¦å å¤æmContentParentæ¯å¦ä¸ºç©ºï¼ç¶åè°ç¨installDecoræ¹æ³ï¼å®è£ è£ é¥°å¨ï¼ï¼æ们ççè¿ä¸ªæ¹æ³å¦ä½å®ç°ç
private void installDecor() {
if (mDecor == null) {
mDecor = generateDecor();
mDecor.setIsRootNamespace(true);
}
if (mContentParent == null) {
mContentParent = generateLayout(mDecor);
mTitleView = (TextView)findViewById(com.android.internal.R.id.title);
if (mTitleView != null) {
if ((getLocalFeatures() & (1 << FEATURE_NO_TITLE)) != 0) {
View titleContainer = findViewById(com.android.internal.R.id.title_container);
if (titleContainer != null) {
titleContainer.setVisibility(View.GONE);
} else {
mTitleView.setVisibility(View.GONE);
}
if (mContentParent instanceof FrameLayout) {
((FrameLayout)mContentParent).setForeground(null);
}
} else {
mTitleView.setText(mTitle);
}
}
}
}
å¨è¯¥æ¹æ³ä¸ï¼é¦å å建ä¸ä¸ªDecorView,DecorViewæ¯ä¸ä¸ªæ©å¼ FrameLayoutçç±»ï¼æ¯ææçªå£çæ ¹Viewãæ们å¨Activityä¸è°ç¨çsetConctentViewå°±æ¯æ¾å°DecorViewä¸äºãè¿æ¯æ们类å¾çèåå ³ç³»å¦ä¸ï¼
Activity--->Window--->DecorView
è¿æ¯æ们å¾åºè¿3个类ä¹é´æç´æ¥çä¸ä¸ªå ³ç³»ã
æ们详ç»åæä¸ä¸ï¼ç±»å¯¹è±¡æ¯å¦ä½è¢«å建çã
å ä¸èèActivityçå建ï¼å 为 Acitivityçå®ä¾ç±ActivityManagerç»´æ¤ï¼æ¯å¨å¦ä¸ä¸ªè¿ç¨è®¾è®¡å°IPCçéä¿¡ï¼åé¢ä¼è®²å°ï¼ï¼èèèWindowåViewçå建ã
Activity被å建åï¼ç³»ç»ä¼è°ç¨å®çattachæ¹æ³æ¥å°Activityæ·»å å°ActivityThreadå½ä¸ãæ们æ¾å°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,
Object lastNonConfigurationInstance,
HashMap<String,Object> lastNonConfigurationChildInstances,
Configuration config) {
attachBaseContext(context);
mWindow= PolicyManager.makeNewWindow(this);
mWindow.setCallback(this);
if (info.softInputMode != WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED) {
mWindow.setSoftInputMode(info.softInputMode);
}
mUiThread = Thread.currentThread();
mMainThread = aThread;
mInstrumentation = instr;
mToken = token;
mIdent = ident;
mApplication = application;
mIntent = intent;
mComponent = intent.getComponent();
mActivityInfo = info;
mTitle = title;
mParent = parent;
mEmbeddedID = id;
mLastNonConfigurationInstance = lastNonConfigurationInstance;
mLastNonConfigurationChildInstances = lastNonConfigurationChildInstances;
mWindow.setWindowManager(null, mToken, mComponent.flattenToString());
if (mParent != null) {
mWindow.setContainer(mParent.getWindow());
}
mWindowManager = mWindow.getWindowManager();
mCurrentConfig = config;
}
æ们ç红è²ç代ç é¨åï¼å°±æ¯å建Window对象ç代ç ãæå ´è¶£çåå¦å¯ä»¥è·è¸ªå»ççå ·ä½æ¯å¦ä½å建çãå ¶å®å¾ç®åï¼å ¶å é¨å®ç°è°ç¨äºPolicy对象çmakeNewWindowæ¹æ³ï¼å ¶æ¹æ³ç´æ¥newäºä¸ä¸ªPhoneWindow对象å¦ä¸ï¼
public PhoneWindow makeNewWindow(Context context) {
return new PhoneWindow(context);
}
è¿æ¶æ们已ç»å¯ä»¥ææµç¨ä¸²èµ·æ¥ï¼Activityå建åç³»ç»ä¼è°ç¨å ¶attachæ¹æ³ï¼å°å ¶æ·»å å°ActivityThreadå½ä¸ï¼å¨attachæ¹æ³ä¸å建äºä¸ä¸ªwindow对象ã
ä¸é¢åæViewçå建ãæ们ç¥éWindowèåäºDocerView,å½ç¨æ·è°ç¨setContentViewçæ¶åä¼æä¸é¢Viewæ ä»ç»DocerView.Viewæ æ¯å·²ç»å建好çå®ä¾å¯¹è±¡äºï¼æ以æ们ç 究çæ¯DocerViewæ¯ä¸ªä»ä¹ä¸è¥¿ï¼å®æ¯å¦ä½è¢«å建çã
æ们å头ççWindowå®ç°éè¾¹çsetContentViewæ¹æ³ï¼æ们çä¸é¢ä»£ç ç红è²é¨åsetContentView-> installDecor-> generateDecor.
generateDecorç´æ¥newäºä¸ä¸ªDecorView对象ï¼
protected DecorView generateDecor() {
return new DecorView(getContext(), -1);
}
æ们å¯ä»¥å»ççDecorViewçå®ç°ï¼å®æ¯PhoneWindowçä¸ä¸ªå é¨ç±»ãå®ç°å¾ç®åï¼å®é»è®¤ä¼å å«ä¸ä¸ªç°è²çæ é¢æ ï¼ç¶åå¨æ é¢æ ä¸è¾¹ä¼å å«ä¸ä¸ªç©ºç½åºåç¨æ¥å½ç¨æ·è°ç¨setContentViewçæ¶åæ¾ç½®ç¨æ·Viewï¼å¹¶ä¼ éäºä»¶ï¼è¿éä¸å详ç»åæï¼æå ´è¶£åå¦å¯ä»¥èªå·±ç 究ç 究ã
å½DecorViewå建好ä¹åååå°Windowä¸çsetContentViewæ¹æ³ä¸æ¥ï¼è§ä¸é¢ä»£ç èè²é¨åï¼è°ç¨
mContentParent.addView(view, params);
æ¥å°ç¨æ·çViewæ æ·»å å°DecorViewä¸ã
å°è¿æ¶ä¸ºæ¢ï¼ææ³æ们已ç»å¾æ¸ æ°ç认è¯å°å®ä»¬3è ä¹é´çå ³ç³»ï¼å¹¶ç¥éå ¶å建æµç¨ã
ç°å¨æ»ç»ä¸ä¸ï¼
Activityå¨onCreateä¹åè°ç¨attachæ¹æ³ï¼å¨attachæ¹æ³ä¸ä¼å建window对象ãwindow对象å建æ¶å¹¶æ¨æå建Decor对象对象ãç¨æ·å¨Activityä¸è°ç¨setContentView,ç¶åè°ç¨windowçsetContentViewï¼è¿æ¶ä¼æ£æ¥DecorViewæ¯å¦åå¨ï¼å¦æä¸åå¨åå建DecorView对象ï¼ç¶åæç¨æ·èªå·±çView æ·»å å°DecorViewä¸ã
2024-12-28 15:45
2024-12-28 15:04
2024-12-28 14:45
2024-12-28 14:16
2024-12-28 14:14
2024-12-28 13:19