Android如何获window对象,Android Window机制

本文详细介绍了Android中Window的添加与移除过程,包括`addView`和`removeView`方法的实现,涉及WindowManagerGlobal、ViewRootImpl和WindowManagerService的角色。此外,还探讨了Dialog和Toast的显示原理,强调了它们与Window的关系以及涉及到的IPC过程和权限管理。
摘要由CSDN通过智能技术生成

Window的简单使用

public void addView(View view){

mFloatingButton = new Button(this);

mFloatingButton.setOnTouchListener(new View.OnTouchListener() {

@Override

public boolean onTouch(View v, MotionEvent event) {

switch (event.getAction()){

case MotionEvent.ACTION_MOVE:

mWindowParams.x = (int) event.getRawX();

mWindowParams.y = (int) event.getRawY();

//window更新操作

mWindowManager.updateViewLayout(mFloatingButton,mWindowParams);

break;

default:

break;

}

return true;

}

});

mFloatingButton.setText("bottom");

mWindowParams = new WindowManager.LayoutParams(WindowManager.LayoutParams.WRAP_CONTENT

,WindowManager.LayoutParams.WRAP_CONTENT,0,0, PixelFormat.TRANSPARENT);

mWindowParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL

| WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED;

mWindowParams.gravity = Gravity.LEFT | Gravity.TOP;

mWindowParams.x = 100;

mWindowParams.y = 300;

//8.0以上使用TYPE_APPLICATION_OVERLAY 8.0以下使用Error

mWindowParams.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY ;

//新增window操作

mWindowManager.addView(mFloatingButton,mWindowParams);

}

//移出window操作

public void removeView(View view){

if (null != mWindowManager){

mWindowManager.removeView(mFloatingButton);

}

}

应用Window层级分为1-99 ,子window层级范围是1000-1999,系统window层级范围是2000-2999.

通过一下代码设置:

mWindowParams.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY ;

需要配置系统弹窗权限:

Window内部机制

addView方法

通过下面代码获取到WindowManager对象。

WindowManager windowManager = (WindowManager) getSystemService(Context.WINDOW_SERVICE);

WindowManager是接口类,继承ViewManager接口。提供addView updateViewLayout removeView方法。实现类为WindowManagerImpl。

mWindowManager = ((WindowManagerImpl)wm).createLocalWindowManager(this);

所以我们看一下WindowManagerImpl的相关操作方法:

@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);

}

可以发现WindowManagerImpl并没有直接实现Window的相关操作方法,而是通过WindowManagerGlobal类来处理的。WindowManagerrGlobal的addView主要有以下几个操作:

1.检测参数是否合法,如果是子Window则需要调整布局参数,不是则针对是否硬件加速做处理

if (view == null) {

throw new IllegalArgumentException("view must not be null");

}

if (display == null) {

throw new IllegalArgumentException("display must not be null");

}

if (!(params instanceof WindowManager.LayoutParams)) {

throw new IllegalArgumentException("Params must be WindowManager.LayoutParams");

}

final WindowManager.LayoutParams wparams = (WindowManager.LayoutParams) params;

if (parentWindow != null) {

parentWindow.adjustLayoutParamsForSubWindow(wparams);

} else {

// If there's no parent, then hardware acceleration for this view is

// set from the application's hardware acceleration setting.

final Context context = view.getContext();

if (context != null

&& (context.getApplicationInfo().flags

& ApplicationInfo.FLAG_HARDWARE_ACCELERATED) != 0) {

wparams.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;

}

}

2.观测系统属性变化

// Start watching for system property changes.

if (mSystemPropertyUpdater == null) {

mSystemPropertyUpdater = new Runnable() {

@Override public void run() {

synchronized (mLock) {

for (int i = mRoots.size() - 1; i >= 0; --i) {

mRoots.get(i).loadSystemProperties();

}

}

}

};

SystemProperties.addChangeCallback(mSystemPropertyUpdater);

}

3.判断添加的view是否是之前删除的view,如果是立即调用dodie方法删除

int index = findViewLocked(view, false);

if (index >= 0) {

if (mDyingViews.contains(view)) {

// Don't wait for MSG_DIE to make it's way through root's queue.

mRoots.get(index).doDie();

} else {

throw new IllegalStateException("View " + view

+ " has already been added to the window manager.");

}

// The previous removeView() had not completed executing. Now it has.

}

4.创建ViewRootImpl并将View添加到列表中

在WindowManagerGlobal中有几个重要的列表:

private final ArrayList mViews = new ArrayList();

private final ArrayList mRoots = new ArrayList();

private final ArrayList mParams =

new ArrayList();

private final ArraySet mDyingViews = new ArraySet();

其中mViews存储的是所以Window对应的view,mRoots存储的是Window对应的ViewRootImpl,mParams存储的是Window对应的布局参数,mDyingViews存储的是正在被删除的View对象,也就是那些调用了removeView方法但是删除操作还没完成的Window对象。在addView方法中将Window一系列对象存储到列表中:

root = new ViewRootImpl(view.getContext(), display);

view.setLayoutParams(wparams);

mViews.add(view);

mRoots.add(root);

mParams.add(wparams);

5.通过ViewRootImpl更新界面并完成Window的添加过程:

root.setView(view, wparams, panelParentView);

通过ViewRootImpl.setView方法来完成。在setView内部通过requestLayout来完成异步刷新请求。下面的代码中scheduleTraversals实际上是view绘制的入口:

public void requestLayout() {

f (!mHandlingLayoutInLayoutRequest) {

checkThread();

mLayoutRequested = true;

scheduleTraversals();

}

}

然后通过WindowSession完成Window的添加过程。

mOrigWindowType = mWindowAttributes.type;

mAttachInfo.mRecomputeGlobalAttributes = true;

collectViewAttributes();

res = mWindowSession.addToDisplay(mWindow, mSeq, mWindowAttributes,

getHostVisibility(), mDisplay.getDisplayId(), mTmpFrame,

mAttachInfo.mContentInsets, mAttachInfo.mStableInsets,

mAttachInfo.mOutsets, mAttachInfo.mDisplayCutout, mInputChannel,

setFrame(mTmpFrame);

上面的代码中,mWindowSession类型是IWindowSession,它是一个binder对象,实现类是Session,也就是说Window添加过程其实是一次IPC的过程。

Session内部通过WindowManagerService来实现Window的添加代码如下:

@Override

public int addToDisplay(IWindow window, int seq, WindowManager.LayoutParams attrs,

int viewVisibility, int displayId, Rect outFrame, Rect outContentInsets,

Rect outStableInsets, Rect outOutsets,

DisplayCutout.ParcelableWrapper outDisplayCutout, InputChannel outInputChannel,

InsetsState outInsetsState) {

return mService.addWindow(this, window, seq, attrs, viewVisibility, displayId, outFrame,

outContentInsets, outStableInsets, outOutsets, outDisplayCutout, outInputChannel,

outInsetsState);

}

这样一来,Window添加请求就交

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值