学习自Android源码设计模式
首先看Dialog的构造函数
Dialog(@NonNull Context context, @StyleRes int themeResId, boolean createContextThemeWrapper) {
//获取WindowManager
mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
//创建Window
final Window w = new PhoneWindow(mContext);
//把WindowManager设置到Window里去
w.setWindowManager(mWindowManager, null, null);
}
继续
public void setWindowManager(WindowManager wm, IBinder appToken, String appName,
boolean hardwareAccelerated) {
if (wm == null) {
wm = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
}
//创建本地WindowManager,传入自己这个Window
mWindowManager = ((WindowManagerImpl)wm).createLocalWindowManager(this);
}
关注WindowImpl.addView
public void addView(View view, Display display, Window parentWindow) {
ViewRootImpl root;
synchronized (mLock) {
root = new ViewRootImpl(view.getContext(), display);
mViews.add(view);//这些都是ArrayList
mRoots.add(root);
mParams.add(wparams);//wparams是由ViewGroup.Params转化而来的Window.params
try {
root.setView(view, wparams, panelParentView);//把view设置到ViewRootImpl中
} catch (RuntimeException e) {
}
}
}
ViewRootImpl构造函数
public ViewRootImpl(Context context, Display display) {
//获取WindowSession,也就是与WMS交互
mWindowSession = WindowManagerGlobal.getWindowSession();
}
继续
public static IWindowSession getWindowSession() {
synchronized (WindowManagerGlobal.class) {
if (sWindowSession == null) {
try {
InputMethodManager imm = InputMethodManager.getInstance();
//获取WMS
IWindowManager windowManager = getWindowManagerService();
//建立session
sWindowSession = windowManager.openSession(
new IWindowSessionCallback.Stub() {
@Override
public void onAnimatorScaleChanged(float scale) {
ValueAnimator.setDurationScale(scale);
}
},
imm.getClient(), imm.getInputContext());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
return sWindowSession;
}
}
继续
public static IWindowManager getWindowManagerService() {
synchronized (WindowManagerGlobal.class) {
if (sWindowManagerService == null) {
sWindowManagerService = IWindowManager.Stub.asInterface(
ServiceManager.getService("window"));//无疑ServiceManager.getService("window")获取的是IBinder
try {
if (sWindowManagerService != null) {
ValueAnimator.setDurationScale(
sWindowManagerService.getCurrentAnimatorScale());
}
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
return sWindowManagerService;
}
}
继续
public static IBinder getService(String name) {
try {
IBinder service = sCache.get(name);
if (service != null) {
return service;
} else {
return Binder.allowBlocking(getIServiceManager().getService(name));
}
} catch (RemoteException e) {
Log.e(TAG, "error in getService", e);
}
return null;
}
session就是Framework 与c(WMS)的交换信息的场所。
WMS管理当前哪个View应该在最上层显示。
接下去看一看ViewRootImpl.setView,这个方法会向WMS发起显示DecorView的请求
public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {
synchronized (this) {
if (mView == null) {
//开始整体绘制
requestLayout();
try {
//向WMS发起请求
res = mWindowSession.addToDisplay(mWindow, mSeq, mWindowAttributes,
getHostVisibility(), mDisplay.getDisplayId(),
mAttachInfo.mContentInsets, mAttachInfo.mStableInsets,
mAttachInfo.mOutsets, mInputChannel);
} catch (RemoteException e) {
} finally {
}
}
看一下熟悉的requestLayout
@Override
public void requestLayout() {
if (!mHandlingLayoutInLayoutRequest) {
checkThread();
mLayoutRequested = true;
scheduleTraversals();
}
}
继续
void scheduleTraversals() {
if (!mTraversalScheduled) {
mTraversalScheduled = true;
mTraversalBarrier = mHandler.getLooper().getQueue().postSyncBarrier();
mChoreographer.postCallback(
Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);
if (!mUnbufferedInputDispatch) {
scheduleConsumeBatchedInput();
}
notifyRendererOfFramePending();
pokeDrawLockIfNeeded();
}
}
继续
final class TraversalRunnable implements Runnable {
@Override
public void run() {
doTraversal();
}
}
继续
void doTraversal() {
if (mTraversalScheduled) {
mTraversalScheduled = false;
mHandler.getLooper().getQueue().removeSyncBarrier(mTraversalBarrier);
if (mProfile) {
Debug.startMethodTracing("ViewAncestor");
}
performTraversals();
if (mProfile) {
Debug.stopMethodTracing();
mProfile = false;
}
}
}
继续
private void performTraversals() {
1.获取Surface对象
2.performMeasure
3.performLayout
4.performDraw
}
在performDraw中,Framework会获取到Surface对象,然后获取它的可绘制区域——>Canvas,然后Framework会在Canvas上绘制。
private void performDraw() {
try {
draw(fullRedrawNeeded);
} finally {
}
}
draw,这个方法会获取需要绘制的区域,以及判断是否采用GPU绘制(通常情况是CPU绘制,即drawSoftware)
private void draw(boolean fullRedrawNeeded) {
//获取Surface
Surface surface = mSurface;
//绘制需要更新
if (!dirty.isEmpty() || mIsAnimating || accessibilityFocusDirty) {
if (mAttachInfo.mThreadedRenderer != null && mAttachInfo.mThreadedRenderer.isEnabled()) {
//GPU绘制(也就是硬件加速)
mAttachInfo.mThreadedRenderer.draw(mView, mAttachInfo, this);
} else {
//CPU绘制
if (!drawSoftware(surface, mAttachInfo, xOffset, yOffset, scalingRequired, dirty)) {
return;
}
}
}
//ps:动画的重复执行主要是因为这里的代码
if (animating) {
mFullRedrawNeeded = true;
scheduleTraversals();
}
}
drawSoftware
private boolean drawSoftware(Surface surface, AttachInfo attachInfo, int xoff, int yoff,
boolean scalingRequired, Rect dirty) {
final Canvas canvas;
try {
final int left = dirty.left;
final int top = dirty.top;
final int right = dirty.right;
final int bottom = dirty.bottom;
//获取指定区域的Canvas,用于Framework绘图
canvas = mSurface.lockCanvas(dirty);
} catch (Surface.OutOfResourcesException e) {
} catch (IllegalArgumentException e) {
}
try {
try
//开始绘制
mView.draw(canvas);
} finally {
}
} finally {
try {
//通知SufaceFlinger更新这块区域
surface.unlockCanvasAndPost(canvas);
} catch (IllegalArgumentException e) {
}
return true;
}
内容绘制完毕后最终请求WMS显示窗口上的内容
需要一个nice的总结:
提一个问题:decor view(主window)何时才会被WindowManagerImpl.addView?
ActivityThread.handleResumeActivity
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 (r.mPreserveWindow) {
a.mWindowAdded = true;
r.mPreserveWindow = false;
ViewRootImpl impl = decor.getViewRootImpl();
if (impl != null) {
impl.notifyChildRebuilt();
}
}
if (a.mVisibleFromClient) {
if (!a.mWindowAdded) {
a.mWindowAdded = true;
wm.addView(decor, l);
} else {
a.onWindowAttributesChanged(l);
}
}
}
wm.addView就是WindowManagerImpl.addView,在这里你的decor view会被添加到WindowManagerGlobal的mViews集合中去。
也是从这里,开始绘制了。
WindowManagerGlobal.setView
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 {
root.setView(view, wparams, panelParentView);
} catch (RuntimeException e) {
// BadTokenException or InvalidDisplayException, clean up.
if (index >= 0) {
removeViewLocked(index, true);
}
throw e;
}
和之前分析的代码几乎一样了。。。
ViewRootImpl.setView中除了requestLayout,还给WMS打了一个信号,那是什么信号?
把让WMS把我这个Window添加到屏幕中去。
(其实上面笔误了,是WindowManagerImpl.addView。还有图中的获取session,这个步骤应该在 new ViewRootImpl(...)里的)