Android 소스 읽기, View 그리기 프로세스 분석
준비 지식:Activity의 시작 프로세스View의 그리기 입구는ActivityThread의handle ResumeActivity에서 볼 수 있습니다.
final void handleResumeActivity(IBinder token,
boolean clearHide, boolean isForward, boolean reallyResume, int seq, String reason) {
ActivityClientRecord r = mActivities.get(token);
// onReStart onStart onResume
r = performResumeActivity(token, clearHide, reason);
if (r != null) {
final Activity a = r.activity;
if (r.window == null && !a.mFinished && willBeVisible) {
r.window = r.activity.getWindow();
View decor = r.window.getDecorView();
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) {
if (!a.mWindowAdded) {
a.mWindowAdded = true;
// View ViewManager--》WindowManager--》WindowManagerImpl( )
// View
wm.addView(decor, l);
}
}
}
}
}
4
2. ViewManager 클래스는 어디에서 생성됩니까?
1. ViewManager wm = a.getWindowManager(); Activity
public WindowManager getWindowManager() {
return mWindowManager;
}
// mWindowManager attch
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,
Window window, ActivityConfigCallback activityConfigCallback) {
attachBaseContext(context);
mFragments.attachHost(null /*parent*/);
mWindow = new PhoneWindow(this, window, activityConfigCallback);
mWindow.setWindowControllerCallback(this);
mWindow.setCallback(this);
mWindow.setOnWindowDismissedCallback(this);
mWindow.getLayoutInflater().setPrivateFactory(this);
//
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());
}
// , WindowManagerImpl
mWindowManager = mWindow.getWindowManager();
mCurrentConfig = config;
mWindow.setColorMode(info.colorMode);
}
public void setWindowManager(WindowManager wm, IBinder appToken, String appName,
boolean hardwareAccelerated) {
mAppToken = appToken;
mAppName = appName;
mHardwareAccelerated = hardwareAccelerated
|| SystemProperties.getBoolean(PROPERTY_HARDWARE_UI, false);
if (wm == null) {
// ViewManager , :WindowManager
wm = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
}
// WindowManagerImpl new
mWindowManager = ((WindowManagerImpl)wm).createLocalWindowManager(this);
}
public WindowManagerImpl createLocalWindowManager(Window parentWindow) {
return new WindowManagerImpl(mContext, parentWindow);
}
클래스 관계: 클래스 윈도 관리자 Impl은 윈도 관리자 인터페이스를 실현하고 윈도 관리자 인터페이스는 ViewManager 인터페이스를 계승한다.
3. WindowManagerImpl 클래스,addView 코드 보기
public final class WindowManagerImpl implements WindowManager {
private final WindowManagerGlobal mGlobal = WindowManagerGlobal.getInstance();
private final Context mContext;
private final Window mParentWindow;
private IBinder mDefaultToken;
private WindowManagerImpl(Context context, Window parentWindow) {
mContext = context;
mParentWindow = parentWindow;
}
public WindowManagerImpl createLocalWindowManager(Window parentWindow) {
return new WindowManagerImpl(mContext, parentWindow);
}
@Override
public void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {
applyDefaultToken(params);
// WindowManagerGlobal.addView
mGlobal.addView(view, params, mContext.getDisplay(), mParentWindow);
}
@Override
public void updateViewLayout(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {
applyDefaultToken(params);
mGlobal.updateViewLayout(view, params);
}
@Override
public void removeView(View view) {
mGlobal.removeView(view, false);
}
@Override
public void removeViewImmediate(View view) {
mGlobal.removeView(view, true);
}
@Override
public void requestAppKeyboardShortcuts(
final KeyboardShortcutsReceiver receiver, int deviceId) {
IResultReceiver resultReceiver = new IResultReceiver.Stub() {
@Override
public void send(int resultCode, Bundle resultData) throws RemoteException {
List result =
resultData.getParcelableArrayList(PARCEL_KEY_SHORTCUTS_ARRAY);
receiver.onKeyboardShortcutsReceived(result);
}
};
try {
WindowManagerGlobal.getWindowManagerService()
.requestAppKeyboardShortcuts(resultReceiver, deviceId);
} catch (RemoteException e) {
}
}
@Override
public Display getDefaultDisplay() {
return mContext.getDisplay();
}
}
넷째, 윈도우 관리자 글로벌 클래스,addView 코드 보기
public void addView(View view, ViewGroup.LayoutParams params,
Display display, Window parentWindow) {
// ViewRootImpl ViewParent
ViewRootImpl root;
View panelParentView = null;
synchronized (mLock) {
// ViewRootImpl
root = new ViewRootImpl(view.getContext(), display);
view.setLayoutParams(wparams);
//
mViews.add(view);
mRoots.add(root);
mParams.add(wparams);
// do this last because it fires off messages to start doing things
try {
// View
root.setView(view, wparams, panelParentView);
} catch (RuntimeException e) {
// BadTokenException or InvalidDisplayException, clean up.
if (index >= 0) {
removeViewLocked(index, true);
}
throw e;
}
}
}
5. ViewRootImpl 클래스, setView 코드 보기
public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {
synchronized (this) {
if (mView == null) {
mView = view;
// N
// ,
requestLayout();
// N
}
}
}
@Override
public void requestLayout() {
if (!mHandlingLayoutInLayoutRequest) {
// UI , View 。
checkThread();
mLayoutRequested = true;
//
scheduleTraversals();
}
}
void scheduleTraversals() {
if (!mTraversalScheduled) {
mTraversalScheduled = true;
mTraversalBarrier = mHandler.getLooper().getQueue().postSyncBarrier();
// Handler mTraversalRunnable 。
// mTraversalRunnable Runnable run()
mChoreographer.postCallback(
Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);
if (!mUnbufferedInputDispatch) {
scheduleConsumeBatchedInput();
}
notifyRendererOfFramePending();
pokeDrawLockIfNeeded();
}
}
6. TraversalRunnable 클래스,run () 코드 보기
final TraversalRunnable mTraversalRunnable = new TraversalRunnable();
final class TraversalRunnable implements Runnable {
@Override
public void run() {
// ViewRootImpl doTraversal()
doTraversal();
}
}
// ViewRootImpl
void doTraversal() {
if (mTraversalScheduled) {
mTraversalScheduled = false;
mHandler.getLooper().getQueue().removeSyncBarrier(mTraversalBarrier);
if (mProfile) {
Debug.startMethodTracing("ViewAncestor");
}
// View 、 、
performTraversals();
if (mProfile) {
Debug.stopMethodTracing();
mProfile = false;
}
}
}
// ViewRootImpl
private void performTraversals() {
// ... N
// View
performMeasure(childWidthMeasureSpec, childHeightMeasureSpec);
// View
performLayout(lp, mWidth, mHeight);
// View
performDraw();
// ... N
}
7.perform Measure,perform Layout,perform Draw 세 가지 방법을 총괄
1. perform Measure(child Width Measure Spec,child Height Measure Spec) --> mView.measure(childWidthMeasureSpec, childHeightMeasureSpec) --> onMeasure(widthMeasureSpec, heightMeasureSpec);
1. performMeasure 。
2. ViewGrop, View , View 。
3. View, View 。
2. perform Layout(lp, mWidth, mHeight) -->> host.layout(0, 0, host.getMeasuredWidth(), host.getMeasuredHeight()); -->> onLayout(changed, l, t, r, b);
1. 。
2. ViewGrop, View, View child.layout(l,t,r,b) View。
3. View 。
3. performDraw()-->drawSoftware()-->mView.draw(canvas); --> drawBackground(canvas);-->onDraw(canvas);--> dispatchDraw(canvas);--> onDrawForeground(canvas);
1. View
2. , View ViewGrop 。
3. ViewGrop, dispatchDraw , View draw() , View。
4. View, onDraw(canvas) 。
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSONJSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다. 그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다. 저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.