前言
??为了描述Activity&Window&ViewRootImpl的关系,我们分别从以下三个阶段进行分析:
- Activity的启动流程;
- Activity的onCreate()阶段;
- Activity的resume流程;
一、Activity启动流程
??在Activity启动流程分析中分析过,App进程创建后,会在ActivityThread的performLaunchActivity()方法中会创建Activity实例。
1.1 ActivityThread.performLaunchActivity
??在ActivityThread.performLaunchActivity()执行流程中,和Window相关的代码从attach()方法开始分析:
public final class ActivityThread extends ClientTransactionHandler {
private Activity performLaunchActivity(ActivityThread.ActivityClientRecord r, Intent customIntent) {
Activity activity = null;
java.lang.ClassLoader cl = appContext.getClassLoader();
activity = mInstrumentation.newActivity(
cl, component.getClassName(), r.intent);
activity.attach(appContext, this, getInstrumentation(), r.token,
r.ident, app, r.intent, r.activityInfo, title, r.parent,
r.embeddedID, r.lastNonConfigurationInstances, config,
r.referrer, r.voiceInteractor, window, r.configCallback,
r.assistToken);
}
}
1.2 Window & PhoneWindow
??attach()方法中会涉及到创建Window。Window 是个抽象类,其具体实现类是 PhoneWindow,Activity 和 Dialog 中的 Window 对象都是 PhoneWindow。
??在Activity的attach()方法内创建了PhoneWindow对象,然后PhoneWindow内创建了WindowManager(WindowManager用来与系统进程system_server通信):
public class Activity {
final void attach(Context context, ActivityThread aThread,
Instrumentation instr, IBinder token ...) {
mWindow = new PhoneWindow(this, window, activityConfigCallback);
mWindow.setCallback(this);
mWindow.setWindowManager(
(WindowManager)context.getSystemService(Context.WINDOW_SERVICE),
mToken, mComponent.flattenToString(),
(info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0);
mWindowManager = mWindow.getWindowManager();
}
}
??在mWindow.setWindowManager()方法内会创建WindowManager对象,代码分析如下。
1.3 WindowManager & WindowManagerImpl
??WindowManager是个接口,WindowManagerImpl其具体实现。每个Activity对应一个WindowManagerImpl。
public abstract class Window {
public void setWindowManager(WindowManager wm, IBinder appToken, String appName,
boolean hardwareAccelerated) {
if (wm == null) {
wm = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
}
mWindowManager = ((WindowManagerImpl)wm).createLocalWindowManager(this);
}
}
??WindowManagerImpl中有个WindowManagerGlobal,所有WindowManagerGlobal都是用了这个单例,后面会涉及到:
public final class WindowManagerImpl implements WindowManager{
private final WindowManagerGlobal mGlobal = WindowManagerGlobal.getInstance();
}
1.4 总结
??Activity的启动过程中,在ActivityThread的performLaunchActivity()方法中会创建Activity实例,接着Activity的attach()方法内会创建PhoneWindow,接着PhoneWindow会创建WindowManagerImpl,在创建WindowManagerImpl时会将mToken(IBinder类型)传给WindowManagerImpl,系统服务WindowManagerService和WindowManagerImpl就是通过mToken(IBinder类型)用Binder机制进行互相通信的。
二、Activity的onCreate()阶段
??在自定义Activity时,我们一般会在Activity的onCreate()方法内调用setContentView(),将layout布局设置给Activity:
public class MainActivity extends Activity{
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
}
??接下来,主要来看下这个过程有哪些涉及到Window的地方。
2.1 setContentView()
??在Activty的setContentView()方法内会调用PhoneWindow的setContentView()方法,PhoneWindow的setContentView()方法内会创建DecorView:
public class Activity {
public void setContentView(@LayoutRes int layoutResID) {
getWindow().setContentView(layoutResID);
initWindowDecorActionBar();
}
}
??PhoneWindow的setContentView()方法内创建DecorView的代码如下:
public class PhoneWindow extends Window implements MenuBuilder.Callback {
public void setContentView(int layoutResID) {
if (mContentParent == null) {
installDecor();
} else if (!hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
mContentParent.removeAllViews();
}
}
private void installDecor() {
if (mDecor == null) {
mDecor = generateDecor(-1);
} else {
mDecor.setWindow(this);
}
}
protected DecorView generateDecor(int featureId) {
return new DecorView(context, featureId, this, getAttributes());
}
}
2.2 总结
??在Activty的setContentView()方法内会调用PhoneWindow的setContentView()方法,PhoneWindow的setContentView()方法内会创建DecorView,之后PhoneWindow和DecorView彼此关联。
三、Activity的resume流程
??与Activity启动流程类似,Activity的resume流程也会经历系统进程然后调用到ActivityThread,下面首先来看下ActivityThread.handleResumeActivity()的逻辑。
3.1 ActivityThread.handleResumeActivity()
??在ActivityThread.handleResumeActivity()中,主要分析两个部分:(1)WindowManagerGlobal内创建ViewRootImpl;(2)WindowManager与DecorView相关联的过程。 重点了解第一个部分,第二个部分简单了解即可。
public final class ActivityThread {
public void handleResumeActivity(IBinder token, boolean finalStateRequest, boolean isForward,
String reason) {
final android.app.ActivityThread.ActivityClientRecord r = performResumeActivity(token, finalStateRequest, reason);
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();
if (a.mVisibleFromClient) {
if (!a.mWindowAdded) {
a.mWindowAdded = true;
wm.addView(decor, l);
} else {
a.onWindowAttributesChanged(l);
}
}
}
if (!r.activity.mFinished && willBeVisible && r.activity.mDecor != null && !r.hideForNow) {
ViewRootImpl impl = r.window.getDecorView().getViewRootImpl();
if (r.activity.mVisibleFromClient) {
r.activity.makeVisible();
}
}
Looper.myQueue().addIdleHandler(new android.app.ActivityThread.Idler());
}
}
3.2 WindowManagerImpl
??在第一章的Activity启动流程中分析过,启动流程中会创建一个PhoneWindow和一个WindowManagerImpl,每个Activity对应一个WindowManagerImpl。WindowManagerImpl内持有WindowManagerGlobal单例。
public final class WindowManagerImpl {
private final WindowManagerGlobal mGlobal = WindowManagerGlobal.getInstance();
public void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {
mGlobal.addView(view, params, mContext.getDisplayNoVerify(), mParentWindow,
mContext.getUserId());
}
}
3.2.1 WindowManagerGlobal
??WindowManagerGlobal是单例类,且调用系统服务的相关代码WindowManagerGlobal.getWindowManagerService()、WindowManagerGlobal.getWindowSession()也是单例实现:
public final class WindowManagerGlobal {
public static WindowManagerGlobal getInstance() {
synchronized (WindowManagerGlobal.class) {
if (sDefaultWindowManager == null) {
sDefaultWindowManager = new WindowManagerGlobal();
}
return sDefaultWindowManager;
}
}
public static IWindowManager getWindowManagerService() {
synchronized (WindowManagerGlobal.class) {
if (sWindowManagerService == null) {
sWindowManagerService = IWindowManager.Stub.asInterface(
ServiceManager.getService("window"));
try {
if (sWindowManagerService != null) {
ValueAnimator.setDurationScale(
sWindowManagerService.getCurrentAnimatorScale());
sUseBLASTAdapter = sWindowManagerService.useBLAST();
}
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
return sWindowManagerService;
}
}
public static IWindowSession getWindowSession() {
synchronized (WindowManagerGlobal.class) {
if (sWindowSession == null) {
try {
InputMethodManager.ensureDefaultInstanceForDefaultDisplayIfNecessary();
IWindowManager windowManager = getWindowManagerService();
sWindowSession = windowManager.openSession(
new IWindowSessionCallback.Stub() {
@Override
public void onAnimatorScaleChanged(float scale) {
ValueAnimator.setDurationScale(scale);
}
});
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
return sWindowSession;
}
}
}
??WindowManagerGlobal单例类内管理着所有DecorView,ViewRootImpl也是在WindowManagerGlobal.addView()内完成创建的,代码分析如下:
public final class WindowManagerGlobal {
private final ArrayList<View> mViews = new ArrayList<View>();
private final ArrayList<ViewRootImpl> mRoots = new ArrayList<ViewRootImpl>();
private final ArrayList<WindowManager.LayoutParams> mParams =
new ArrayList<WindowManager.LayoutParams>();
public void addView(View view, ViewGroup.LayoutParams params,
Display display, Window parentWindow, int userId) {
ViewRootImpl root;
View panelParentView = null;
synchronized (mLock) {
root = new ViewRootImpl(view.getContext(), display);
view.setLayoutParams(wparams);
mViews.add(view);
mRoots.add(root);
mParams.add(wparams);
root.setView(view, wparams, panelParentView, userId);
}
}
public static IWindowSession getWindowSession() {
synchronized (android.view.WindowManagerGlobal.class) {
if (sWindowSession == null) {
try {
InputMethodManager.ensureDefaultInstanceForDefaultDisplayIfNecessary();
IWindowManager windowManager = getWindowManagerService();
sWindowSession = windowManager.openSession(
new IWindowSessionCallback.Stub() {
@Override
public void onAnimatorScaleChanged(float scale) {
ValueAnimator.setDurationScale(scale);
}
});
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
return sWindowSession;
}
}
}
3.2.2 ViewRootImpl
??ViewRootImpl是一个很常见的类了,ViewRootImpl不是一个View,我们所熟悉的View绘制流程中的performMeasure()、performLayout()、performDraw()都是在performTraversals()方法中顺序调用的。本次不涉及到绘制流程分析,只分析ViewRootImpl创建过程中做了哪些操作。
??ViewRootImpl创建过程中,创建了SurfaceHolder,并调用系统服务进程WindowManagerService,系统服务进程会创建Surface与SurfaceFlinger:
public final class ViewRootImpl implements ViewParent,
View.AttachInfo.Callbacks, ThreadedRenderer.DrawCallbacks {
public ViewRootImpl(Context context, Display display) {
this(context, display, android.view.WindowManagerGlobal.getWindowSession(),
false );
}
public ViewRootImpl(Context context, Display display, IWindowSession session,
boolean useSfChoreographer) {
mContext = context;
mWindowSession = session;
mDisplay = display;
mBasePackageName = context.getBasePackageName();
mThread = Thread.currentThread();
mWindow = new android.view.ViewRootImpl.W(this);
mChoreographer = useSfChoreographer
? Choreographer.getSfInstance() : Choreographer.getInstance();
mDisplayManager = (DisplayManager)context.getSystemService(Context.DISPLAY_SERVICE);
}
public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView,
int userId) {
synchronized (this) {
if (mView == null) {
mView = view;
if (view instanceof RootViewSurfaceTaker) {
mSurfaceHolderCallback =
((RootViewSurfaceTaker)view).willYouTakeTheSurface();
if (mSurfaceHolderCallback != null) {
mSurfaceHolder = new android.view.ViewRootImpl.TakenSurfaceHolder();
mSurfaceHolder.setFormat(PixelFormat.UNKNOWN);
mSurfaceHolder.addCallback(mSurfaceHolderCallback);
}
}
requestLayout();
res = mWindowSession.addToDisplayAsUser(mWindow, mSeq, mWindowAttributes,
getHostVisibility(), mDisplay.getDisplayId(), userId, mTmpFrame,
mAttachInfo.mContentInsets, mAttachInfo.mStableInsets,
mAttachInfo.mDisplayCutout, inputChannel,
mTempInsets, mTempControls);
setFrame(mTmpFrame);
}
}
}
}
3.3 Activity.makeVisible()
??将启动流程中创建的WindowManager与onCreate阶段创建的DecorView关联起来的代码比较简单:
public class Activity {
void makeVisible() {
if (!mWindowAdded) {
ViewManager wm = getWindowManager();
wm.addView(mDecor, getWindow().getAttributes());
mWindowAdded = true;
}
mDecor.setVisibility(View.VISIBLE);
}
}
3.4 总结
- 在Activity的启动流程中,会创建一个PhoneWindow和一个WindowManagerImpl,每个Activity对应一个WindowManagerImpl。
- 在Activty的setContentView()方法内会调用PhoneWindow的setContentView()方法,PhoneWindow的setContentView()方法内会创建DecorView:
- 在Activity的resume流程中,会调用WindowManagerGlobal创建ViewRootImpl,接着ViewRootImpl会创建SurfaceHolder,并通过WindowManagerGlobal.getWindowSession()调用系统服务WindowManagerService创建Surface与SurfaceFlinger;
- 每个PhoneWindow都持有WindowManagerGlobal单例,WindowManagerGlobal管理着所有的ViewRootImpl和DecorView.
??至此,Activity&Window&ViewRootImpl的关系分析结束。
四、Dialog
??在Dialog的创建过程中,也与Activity相似的创建PhoneWindow、ViewRootImp流程。例如,一般自定义Dialog的的操作如下:
Dialog dialog = new Dialog(this);
dialog.setContentView(R.layout.bc_dialog_layout);
dialog.show();
??其中主要来分析Dialog构造函数和Dialog.setContent()、Dialog.show()方法,在构造函数中创建了PhoneWindow,在Dialog.setContent()方法中创建了DecorView、在Dialog.show()方法中创建了ViewRootImp:
public class Dialog{
private Activity mOwnerActivity;
private final WindowManager mWindowManager;
final Context mContext;
final Window mWindow;
View mDecor;
Dialog(Context context, int themeResId, boolean createContextThemeWrapper) {
mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
final Window w = new PhoneWindow(mContext);
mWindow = w;
w.setCallback(this);
w.setOnWindowDismissedCallback(this);
w.setOnWindowSwipeDismissedCallback(() -> {
if (mCancelable) {
cancel();
}
});
w.setWindowManager(mWindowManager, null, null);
w.setGravity(Gravity.CENTER);
mListenersHandler = new android.app.Dialog.ListenersHandler(this);
}
public void setContentView(int layoutResID) {
mWindow.setContentView(layoutResID);
}
public void show() {
if (mShowing) {
if (mDecor != null) {
if (mWindow.hasFeature(Window.FEATURE_ACTION_BAR)) {
mWindow.invalidatePanelMenu(Window.FEATURE_ACTION_BAR);
}
mDecor.setVisibility(View.VISIBLE);
}
return;
}
onStart();
mDecor = mWindow.getDecorView();
WindowManager.LayoutParams l = mWindow.getAttributes();
mWindowManager.addView(mDecor, l);
mShowing = true;
sendShowMessage();
}
}
五、抽象的Window
??Window本身是一个抽象的概念,例如按照以下方式也可以显示一个View,这个过程并没有真正创建PhoneWindow,但是把自定义view所在抽象window的parentWindow设置为了Activity的Window。
View view = LayoutInflater.from(this).inflate(R.layout.layout_bc_window, null);
int flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
| WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
| WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED;
WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams(
WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.TYPE_SYSTEM_ERROR, flags,
PixelFormat.TRANSPARENT);
layoutParams.gravity = Gravity.CENTER;
layoutParams.x = 0;
layoutParams.y = 0;
WindowManager windowManager = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
windowManager.addView(view, layoutParams);
The End
欢迎关注我,一起解锁更多技能:BC的掘金主页~💐?BC的CSDN主页~💐💐
在线查看Android源码:https://cs.android.com/
Android源码下载:https://source.android.google.cn/setup/downloading?hl=zh-cn
Anroid studio内源码查看方法:https://github.com/anggrayudi/android-hidden-api
|