You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
141 lines
3.3 KiB
141 lines
3.3 KiB
5 years ago
|
---
|
||
|
Activity 的显示原理
|
||
|
---
|
||
|
|
||
|
1. Activity 的显示原理(Window/DecorView/ViewRoot)
|
||
|
2. Activity 的 UI 刷新机制(Vsync/Choreographer)
|
||
|
3. UI 的绘制原理(Measure/Layout/Draw)
|
||
|
4. Surface 原理(Surface/SurfaceFlinger)
|
||
|
|
||
|
#### 显示原理
|
||
|
|
||
|
1. setContentView 原理是什么?
|
||
|
2. Activity 在 onResume 之后才会显示的原因是什么?
|
||
|
3. ViewRoot 是干嘛的,是 View Tree 的 rootView 么?
|
||
|
|
||
|
```java
|
||
|
public void setContentView(int layoutResID) {
|
||
|
getWindow().setContentView(layoutResID);
|
||
|
//...
|
||
|
}
|
||
|
```
|
||
|
|
||
|
```java
|
||
|
final void attach(Context context, ){
|
||
|
mWindow = new PhoneWindow(this);
|
||
|
}
|
||
|
```
|
||
|
|
||
|
```java
|
||
|
// PhoneWindow#setContentView
|
||
|
public void setContentView(int layoutResID) {
|
||
|
if(mContentParent == null) {
|
||
|
installDecor();
|
||
|
}
|
||
|
mLayoutInflater.inflate(layoutResID, mContentParent);
|
||
|
}
|
||
|
|
||
|
private void installDecor() {
|
||
|
// FrameLayout
|
||
|
mDecor = new DecorView(getContext());
|
||
|
// 根据 Window Feature 选择一个系统布局
|
||
|
View in = mLayoutInflater.inflate(layoutResource, null);
|
||
|
mDecor.addView(in, ...);
|
||
|
mContentParent = findViewById(ID_ANDROID_CONTENT);
|
||
|
}
|
||
|
```
|
||
|
|
||
|
```java
|
||
|
final void handleResumeActivity(IBinder token) {
|
||
|
ActivityClientRecord r = performResumeActivity(token, );
|
||
|
final Activity a = r.activity;
|
||
|
|
||
|
if(r.window == null && !a.mFinished) {
|
||
|
r.window = r.activity.getWindow();
|
||
|
View decor = r.window.getDecorView();
|
||
|
|
||
|
ViewManager wm = a.getWindowManager();
|
||
|
a.mDecor = decor;
|
||
|
wm.addview(decor, l);
|
||
|
}
|
||
|
r.activity.makeVisible();
|
||
|
}
|
||
|
```
|
||
|
|
||
|
```java
|
||
|
// ViewManager#addView
|
||
|
void addView(View view, ViewGroup.LayoutParams params, ){
|
||
|
ViewRootImpl root = new ViewRootImpl(view.getContext(), );
|
||
|
root.setView(view, wparams, panelParentView);
|
||
|
}
|
||
|
```
|
||
|
|
||
|
```java
|
||
|
// ViewRootImpl#setView
|
||
|
public void setView(View view, ) {
|
||
|
if(mView == null) {
|
||
|
mView = view;
|
||
|
requestLayout();
|
||
|
//...
|
||
|
mWindowSession.addToDisplay(mWindow, ...);
|
||
|
}
|
||
|
}
|
||
|
```
|
||
|
|
||
|
```java
|
||
|
public void requestLayout() {
|
||
|
scheduleTraversals();
|
||
|
}
|
||
|
void scheduleTraversals() {
|
||
|
mChoreographer.postCallback(..., mTraversalRunnable, null);
|
||
|
}
|
||
|
class TraversalRunnable implements Runnable {
|
||
|
public void run() {
|
||
|
doTraversal();
|
||
|
}
|
||
|
}
|
||
|
void doTraversal() {
|
||
|
performTraversals();
|
||
|
}
|
||
|
private void performTraversals() {
|
||
|
//...
|
||
|
relayoutWindow(params, ...);
|
||
|
performMeasure(childWidthMeasureSpec, ...);
|
||
|
performLayout(lp, desiredWindowWidth, ...);
|
||
|
performDraw();
|
||
|
}
|
||
|
// 向 WMS 申请 Surface
|
||
|
int relayoutWindow(WindowManager.LayoutParams params, ...) {
|
||
|
mWindowSession.relayout(..., mSurface);
|
||
|
}
|
||
|
```
|
||
|
|
||
|
```java
|
||
|
// static class W extends IWindow.Stub {...}
|
||
|
mWindowSession.addToDisplay(mWindow, ...);
|
||
|
public int addToDisplay(IWindow window, int seq, ...) {
|
||
|
// WMS 统一管理 Window,分配 Surface
|
||
|
return mService.addWindow(this, window, seq, attrs, ...);
|
||
|
}
|
||
|
|
||
|
IWindowManager windowManager = getWindowManagerService();
|
||
|
sWindowSession = windowManager.openSession(...);
|
||
|
|
||
|
IWindowSession openSession(IWindowSessionCallback callback, ...) {
|
||
|
Session session = new Session(this, callback, client, inputContext);
|
||
|
return session;
|
||
|
}
|
||
|
```
|
||
|
|
||
|
WMS 的主要作用:
|
||
|
|
||
|
1. 分配 Surface
|
||
|
2. 掌管 Surface 显示顺序以及位置尺寸等
|
||
|
3. 控制窗口动画
|
||
|
4. 输入事件分发
|
||
|
|
||
|
#### 总结
|
||
|
|
||
|
![](https://i.loli.net/2020/03/23/X2pw9F6B5SmdVRj.png)
|
||
|
|