/ 今日科技快讯 /
近日消息,京东百亿补贴被曝已开始少量上线测试,已有用户可看到活动页面!据网友反馈,京东部分商品现已有“百亿补贴”的标签,目前上线的商品包括手机、家电、酒水、食品、服饰等众多品类。
/ 作者简介 /
大家周五好,咱们下周再见,祝大家周末愉快!
本篇文章转自小余的自习室的博客,文章主要分享了Android WindowManager体系的讲解,相信会对大家有所帮助!
原文地址:
https://juejin.cn/post/7166157765570723871
/ 前言 /
大家好,由于工作和面试需要,笔者结合大佬们的经验以及自身对源码理解,写了一篇关于Android framework层:WindowManager体系的讲解。
本篇是Android framework的第一讲,重在讲解Window在被添加到WindowManagerService前的流程。
/ WindowManager体系 /
Android中的窗口体系可以分为下面三部分:
1. Window:可以简单理解为一个窗口,这个窗口承载了需要绘制的View,他是一个抽象类,具体实现类是PhoneWindow。
2. WindowManager:也是一个接口类,继承ViewManager,用来对Window进行管理, 实现类:WindowManagerImpl,其对Window的操作具体是通过WMS来实现的。理解为一个app层面的WMS和Window的中间人。
3. WindowManagerService(WMS):是系统服务中的一重要成员,WindowManager和WMS通过binder进行通讯,真正对Window添加,更新,删除等操作的执行者。
三者之间关系:
前面分析了窗口体系中的类关系,下面我们从源码角度和分析下:
为了大家不会迷路在源码中,笔者会根据面试中可能被问到的几个问题出发,有目的性的介绍。
问题1:Window和Activity以及WindowManager什么时候建立的关系? 问题2:Window什么时候和View进行关联? 问题3:Window有哪些属性?类型?层级关系?z-order?Window标志?软键盘模式都了解么? 问题4:View是如何一步一步添加到屏幕上的?更新?删除呢?
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);
...
mWindow = new PhoneWindow(this, window, activityConfigCallback);//1
...
mWindow.setWindowManager(
(WindowManager)context.getSystemService(Context.WINDOW_SERVICE),
mToken, mComponent.flattenToString(),
(info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0);//2
}
public class PhoneWindow extends Window {
public PhoneWindow(Context context, Window preservedWindow,
ActivityConfigCallback activityConfigCallback) {
//这里最终会调父类Window的构造方法,并传入Activity的实例context。
this(context);
//只有Activity的Window才会使用Decor context,其他依赖使用的Context
mUseDecorContext = true;
...
}
}
public Window(Context context) {
mContext = context;
mFeatures = mLocalFeatures = getDefaultFeatures(context);
}
public void setWindowManager(WindowManager wm, IBinder appToken, String appName,
boolean hardwareAccelerated) {
//如果wm是空,则创建一个WindowManager服务:注释1
if (wm == null) {
wm = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
}
//注释2
mWindowManager = ((WindowManagerImpl)wm).createLocalWindowManager(this);
}
@Override
public Object getSystemService(String name) {
return SystemServiceRegistry.getSystemService(this, name);
}
进入SystemServiceRegistry的getSystemService方法,name = Context.WINDOW_SERVICE
public static Object getSystemService(ContextImpl ctx, String name) {
ServiceFetcher<?> fetcher = SYSTEM_SERVICE_FETCHERS.get(name);//1
return fetcher != null ? fetcher.getService(ctx) : null;//2
}
static {
...
registerService(Context.WINDOW_SERVICE, WindowManager.class,
new CachedServiceFetcher<WindowManager>() {
@Override
public WindowManager createService(ContextImpl ctx) {
return new WindowManagerImpl(ctx);
}});
}
private static <T> void registerService(String serviceName, Class<T> serviceClass,
ServiceFetcher<T> serviceFetcher)
public WindowManagerImpl createLocalWindowManager(Window parentWindow) {
return new WindowManagerImpl(mContext, parentWindow);
}
public void setContentView(@LayoutRes int layoutResID) {
getWindow().setContentView(layoutResID);//1
initWindowDecorActionBar();//2
}
public void setContentView(int layoutResID) {
...
if (mContentParent == null) {
installDecor();//注释1
}
mLayoutInflater.inflate(layoutResID, mContentParent);//注释2
...
}
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());
}
private void initWindowDecorActionBar() {
Window window = getWindow();
// Initializing the window decor can change window feature flags.
// Make sure that we have the correct set before performing the test below.
window.getDecorView();
if (isChild() || !window.hasFeature(Window.FEATURE_ACTION_BAR) || mActionBar != null) {
return;
}
mActionBar = new WindowDecorActionBar(this);
mActionBar.setDefaultDisplayHomeAsUpEnabled(mEnableDefaultActionBarUp);
...
}
1.设置主题
public void setTheme(int resid) {
super.setTheme(resid);
mWindow.setTheme(resid);
}
2.设置Window属性等
public final boolean requestWindowFeature(int featureId) {
return getWindow().requestFeature(featureId);
}
3.获取Layout解析器
public LayoutInflater getLayoutInflater() {
return getWindow().getLayoutInflater();
}
Window窗口类型(Type)
public static class LayoutParams extends ViewGroup.LayoutParams implements Parcelable {
//应用程序窗口的起始值
public static final int FIRST_APPLICATION_WINDOW = 1;
//应用程序窗口的基准值
public static final int TYPE_BASE_APPLICATION = 1;
//标准的应用程序窗口:依附于Activity存在
public static final int TYPE_APPLICATION = 2;
public static final int TYPE_APPLICATION_STARTING = 3;
public static final int TYPE_DRAWN_APPLICATION = 4;
//应用程序窗口结束值
public static final int LAST_APPLICATION_WINDOW = 99;
...
}
public static class LayoutParams extends ViewGroup.LayoutParams implements Parcelable {
public static final int FIRST_SUB_WINDOW = 1000;//子窗口类型初始值
public static final int TYPE_APPLICATION_PANEL = FIRST_SUB_WINDOW;
public static final int TYPE_APPLICATION_MEDIA = FIRST_SUB_WINDOW + 1;
public static final int TYPE_APPLICATION_SUB_PANEL = FIRST_SUB_WINDOW + 2;
public static final int TYPE_APPLICATION_ATTACHED_DIALOG = FIRST_SUB_WINDOW + 3;
public static final int TYPE_APPLICATION_MEDIA_OVERLAY = FIRST_SUB_WINDOW + 4;
public static final int TYPE_APPLICATION_ABOVE_SUB_PANEL = FIRST_SUB_WINDOW + 5;
public static final int LAST_SUB_WINDOW = 1999;//子窗口类型结束值
...
}
public static class LayoutParams extends ViewGroup.LayoutParams implements Parcelable {
public static final int FIRST_SYSTEM_WINDOW = 2000;//系统窗口类型初始值
public static final int TYPE_STATUS_BAR = FIRST_SYSTEM_WINDOW;//系统状态栏窗口
public static final int TYPE_SEARCH_BAR = FIRST_SYSTEM_WINDOW+1;//搜索条窗口
public static final int TYPE_PHONE = FIRST_SYSTEM_WINDOW+2;//通话窗口
public static final int TYPE_SYSTEM_ALERT = FIRST_SYSTEM_WINDOW+3;//系统ALERT窗口
public static final int TYPE_KEYGUARD = FIRST_SYSTEM_WINDOW+4;//锁屏窗口
public static final int TYPE_TOAST = FIRST_SYSTEM_WINDOW+5;//TOAST窗口
...
public static final int LAST_SYSTEM_WINDOW = 2999;//系统窗口类型结束值
}
Window窗口层级关系(Z-Order)
Window窗口标志(Flag)
Window mWindow =getWindow();
mWindow.addFlags(LayoutParams.FLAG_KEEP_SCREEN_ON);
mWindow.setFlags(LayoutParams.FLAG_KEEP_SCREEN_ON,LayoutParams.FLAG_KEEP_SCREEN_ON);
WindowManager.LayoutParams wl = new WindowManager.LayoutParams();
wl.flags = LayoutParams.FLAG_KEEP_SCREEN_ON;
Log.d("TAG","window:"+window.getWindowManager());
WindowManager mWindowManager = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
TextView mTextView=new TextView(this);
mTextView.setText("ttttttttdddddd");
Log.d("TAG","mWindow:"+mWindowManager);
mWindowManager.addView(mTextView,wl);
Window 软键盘模式(SoftInputModel)
public interface ViewManager{
public void addView(View view, ViewGroup.LayoutParams params);
public void updateViewLayout(View view, ViewGroup.LayoutParams params);
public void removeView(View view);
}
public final class WindowManagerImpl implements WindowManager{
private final WindowManagerGlobal mGlobal = WindowManagerGlobal.getInstance();
@Override
public void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {
applyDefaultToken(params);
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);
}
...
}
public void addView(View view, ViewGroup.LayoutParams params,
Display display, Window parentWindow) {
...
ViewRootImpl root;
//将params强转为WindowManager.LayoutParams类型
final WindowManager.LayoutParams wparams = (WindowManager.LayoutParams) params;
synchronized (mLock) {
//创建一个ViewRootImpl对象
root = new ViewRootImpl(view.getContext(), display);
//给View设置LayoutParams参数
view.setLayoutParams(wparams);
//存储view到mViews列表
mViews.add(view);
//存储root到mRoots列表
mRoots.add(root);
//存储wparams到mParams列表
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;
}
}
}
public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {
...
requestLayout();//注释1
...
res = mWindowSession.addToDisplay(mWindow, mSeq, mWindowAttributes,
getHostVisibility(), mDisplay.getDisplayId(),
mAttachInfo.mContentInsets, mAttachInfo.mStableInsets,
mAttachInfo.mOutsets, mInputChannel);//注释2
...
}
mWindowSession = WindowManagerGlobal.getWindowSession();
public static IWindowSession getWindowSession() {
synchronized (WindowManagerGlobal.class) {
if (sWindowSession == null) {
try {
InputMethodManager imm = InputMethodManager.getInstance();
IWindowManager windowManager = getWindowManagerService();//1
sWindowSession = windowManager.openSession(//2
new IWindowSessionCallback.Stub() {
@Override
public void onAnimatorScaleChanged(float scale) {
ValueAnimator.setDurationScale(scale);
}
},
imm.getClient(), imm.getInputContext());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
return sWindowSession;
}
}
@Override
public IWindowSession openSession(IWindowSessionCallback callback, IInputMethodClient client,
IInputContext inputContext) {
if (client == null) throw new IllegalArgumentException("null client");
if (inputContext == null) throw new IllegalArgumentException("null inputContext");
Session session = new Session(this, callback, client, inputContext);
return session;
}
public int addToDisplay(IWindow window, int seq, WindowManager.LayoutParams attrs,
int viewVisibility, int displayId, Rect outContentInsets, Rect outStableInsets,
Rect outOutsets, InputChannel outInputChannel) {
return mService.addWindow(this, window, seq, attrs, viewVisibility, displayId,
outContentInsets, outStableInsets, outOutsets, outInputChannel);
}
public void removeView(View view, boolean immediate) {
...
synchronized (mLock) {
int index = findViewLocked(view, true);//1
View curView = mRoots.get(index).getView();//2
removeViewLocked(index, immediate);//3
if (curView == view) {
return;
}
throw new IllegalStateException("Calling with view " + view
+ " but the ViewAncestor is attached to " + curView);
}
}
private int findViewLocked(View view, boolean required) {
final int index = mViews.indexOf(view);
if (required && index < 0) {
throw new IllegalArgumentException("View=" + view + " not attached to window manager");
}
return index;
}
private void removeViewLocked(int index, boolean immediate) {
...
boolean deferred = root.die(immediate);
if (view != null) {
view.assignParent(null);
if (deferred) {
mDyingViews.add(view);
}
}
}
boolean die(boolean immediate) {
...
//如果是同步移除,则立即调用doDie方法
if (immediate && !mIsInTraversal) {
doDie();
return false;
}
...
//异步移除,发出一个msg进行移除
mHandler.sendEmptyMessage(MSG_DIE);
return true;
}
void doDie() {
...
synchronized (this) {
if (mAdded) {
dispatchDetachedFromWindow();//1
}
..
}
WindowManagerGlobal.getInstance().doRemoveView(this);//4
}
void dispatchDetachedFromWindow() {
if (mView != null && mView.mAttachInfo != null) {
//这里可以看出我们可以在View销毁前,在View的dispatchDetachedFromWindow做一些资源释放操作
mView.dispatchDetachedFromWindow();
}
//销毁硬件渲染线程
destroyHardwareRenderer();
//将mView的root置为mull
mView.assignParent(null);
mView = null;
mAttachInfo.mRootView = null;
//释放当前Surface
mSurface.release();
//核心移除View的方法。
try {
mWindowSession.remove(mWindow);
} catch (RemoteException e) {
}
//移除同步屏障以及View的绘制task
unscheduleTraversals();
}
public void remove(IWindow window) {
mService.removeWindow(this, window);
}
public void removeWindow(Session session, IWindow client) {
synchronized(mWindowMap) {
// 得到 windowstate 对象
WindowState win = windowForClientLocked(session, client, false);
if (win == null) {
return;
}
// 进行移除 window 操作
removeWindowLocked(win);
}
}