Android知识总结
一、前言
Window的删除过程,本文中从WindowManagerImpl开始讲起,主要做了四个事情如图右所示。
二、源码分析
1、删除窗口视图
public final class ActivityThread extends ClientTransactionHandler {
@Override
public void handleDestroyActivity(IBinder token, boolean finishing, int configChanges,
boolean getNonConfigInstance, String reason) {
//最终执行Activity的onDestroy()
ActivityClientRecord r = performDestroyActivity(token, finishing,
configChanges, getNonConfigInstance, reason);
if (r != null) {
cleanUpPendingRemoveWindows(r, finishing);
WindowManager wm = r.activity.getWindowManager();
View v = r.activity.mDecor;
if (v != null) {
if (r.activity.mVisibleFromServer) {
mNumVisibleActivities--;
}
IBinder wtoken = v.getWindowToken();
if (r.activity.mWindowAdded) {
if (r.mPreserveWindow) {
r.mPendingRemoveWindow = r.window;
r.mPendingRemoveWindowManager = wm;
r.window.clearContentView();
} else {
//进入WindowManagerImpl进行移除相关操作
wm.removeViewImmediate(v);
}
}
if (wtoken != null && r.mPendingRemoveWindow == null) {
WindowManagerGlobal.getInstance().closeAll(wtoken,
r.activity.getClass().getName(), "Activity");
} else if (r.mPendingRemoveWindow != null) {
WindowManagerGlobal.getInstance().closeAllExceptView(token, v,
r.activity.getClass().getName(), "Activity");
}
r.activity.mDecor = null;
}
if (r.mPendingRemoveWindow == null) {
WindowManagerGlobal.getInstance().closeAll(token,
r.activity.getClass().getName(), "Activity");
}
Context c = r.activity.getBaseContext();
if (c instanceof ContextImpl) {
((ContextImpl) c).scheduleFinalCleanup(
r.activity.getClass().getName(), "Activity");
}
}
if (finishing) {
try {
ActivityTaskManager.getService().activityDestroyed(token);
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
}
mSomeActivitiesChanged = true;
}
}
- 进入
WindowManagerImpl
,因为WindowManager继承ViewManager,所以WindowManagerImpl 才有相关的添加,删除和更新操作。
public final class WindowManagerImpl implements WindowManager {
@Override
public void removeView(View view) {
mGlobal.removeView(view, false);
}
//立即移除
@Override
public void removeViewImmediate(View view) {
mGlobal.removeView(view, true);
}
}
- 进入
WindowManagerGlobal
public final class WindowManagerGlobal {
//要销毁试图集合,存放的是DecorView
private final ArraySet mDyingViews = new ArraySet();
public void removeView(View view, boolean immediate) {
if (view == null) {
throw new IllegalArgumentException("view must not be null");
}
synchronized (mLock) {
//获取 View 在集合中的位置
int index = findViewLocked(view, true);
//获取ViewRootImpl中的DecorView
View curView = mRoots.get(index).getView();
removeViewLocked(index, immediate);
if (curView == view) { //删除的是DecorView 直接返回,否则抛出异常
return;
}
throw new IllegalStateException("Calling with view " + view
+ " but the ViewAncestor is attached to " + curView);
}
}
//获取删除View在mView集合中的索引
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) {
ViewRootImpl root = mRoots.get(index);
View view = root.getView();//DecorView
if (view != null) {
InputMethodManager imm = InputMethodManager.getInstance();
if (imm != null) {
imm.windowDismissed(mViews.get(index).getWindowToken());
}
}
boolean deferred = root.die(immediate);
if (view != null) {
view.assignParent(null);
if (deferred) {
//添加到移除试图集合中
mDyingViews.add(view);
}
}
}
}
2、判断是否立即执行删除
在ViewRootImpl
中die
方法中,会先判断是否立即执行删除,如果被判处死刑且立即执行则调用doDie方法,如果不是则通过Handler方法执行死刑的信号,判个缓刑。
boolean die(boolean immediate) {.
//immediate 是否立即执行 为ture则立即执行删除
if (immediate && !mIsInTraversal) {
doDie();
return false;
}
......
//通过Handler发送死亡信息,判处死缓
//最终执行到 doDie() 方法
mHandler.sendEmptyMessage(MSG_DIE);
return true;
}
void doDie() {
//检查线程
checkThread();
if (LOCAL_LOGV) Log.v(mTag, "DIE in " + this + " of " + mSurface);
synchronized (this) {
//判断是否删除
if (mRemoved) {
return;
}
//防止重复调用
mRemoved = true;
if (mAdded) {
//做数据清除 注销操作,调用session的remove方法
dispatchDetachedFromWindow();
}
if (mAdded && !mFirst) {
destroyHardwareRenderer();
if (mView != null) {
int viewVisibility = mView.getVisibility();
boolean viewVisibilityChanged = mViewVisibility != viewVisibility;
if (mWindowAttributesChanged || viewVisibilityChanged) {
try {
if ((relayoutWindow(mWindowAttributes, viewVisibility, false)
& WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME) != 0) {
mWindowSession.finishDrawing(
mWindow, null /* postDrawTransaction */);
}
} catch (RemoteException e) {
}
}
//销毁画布
destroySurface();
}
}
mAdded = false;
}
//调用WindowManagerGlobal移除方法
WindowManagerGlobal.getInstance().doRemoveView(this);
}
-
ViewRootImpl@checkThread()
检查线程的正确性
void checkThread() {
if (mThread != Thread.currentThread()) {
throw new CalledFromWrongThreadException(
"Only the original thread that created a view hierarchy can touch its views.");
}
}
在ViewRootImpl的dispatchDetachedFromWindow
方法中会调用 Session 与WMS进行通信,然后执行移除的操作。
void dispatchDetachedFromWindow() {
mFirstInputStage.onDetachedFromWindow();
if (mView != null && mView.mAttachInfo != null) {
mAttachInfo.mTreeObserver.dispatchOnWindowAttachedChange(false);
mView.dispatchDetachedFromWindow();
}
mAccessibilityInteractionConnectionManager.ensureNoConnection();
mAccessibilityManager.removeAccessibilityStateChangeListener(
mAccessibilityInteractionConnectionManager);
mAccessibilityManager.removeHighTextContrastStateChangeListener(
mHighContrastTextManager);
removeSendWindowContentChangedCallback();
destroyHardwareRenderer(); //删除硬件渲染
setAccessibilityFocus(null, null);
mView.assignParent(null);
mView = null; //DecorView
mAttachInfo.mRootView = null;
mSurface.release(); //销毁Surface.
if (mInputQueueCallback != null && mInputQueue != null) {
mInputQueueCallback.onInputQueueDestroyed(mInputQueue);
mInputQueue.dispose();
mInputQueueCallback = null;
mInputQueue = null;
}
if (mInputEventReceiver != null) {
mInputEventReceiver.dispose();
mInputEventReceiver = null;
}
try {// 通过IWindowSession 关联到 WMS中删除信息
mWindowSession.remove(mWindow);
} catch (RemoteException e) {
}
if (mInputChannel != null) {
mInputChannel.dispose();
mInputChannel = null;
}
mDisplayManager.unregisterDisplayListener(mDisplayListener);
unscheduleTraversals();
}
在WMS
的removeWindow
函数中,先会通过Session和Client获取到当前窗口在WMS的副本也就是WindowState,如果不为空则执行删除操作。
会进入 Session@remove
方法,Session
时 IWindowSession
的实现类
class Session extends IWindowSession.Stub implements IBinder.DeathRecipient {
final WindowManagerService mService;
@Override
public void remove(IWindow window) {
mService.removeWindow(this, window);
}
}
- 进入到
WindowManagerService@removeWindow
方法
//每个WMS都有一个唯一的 Session
void removeWindow(Session session, IWindow client) {
synchronized (mGlobalLock) {
//获取WindowState
WindowState win = windowForClientLocked(session, client, false);
if (win != null) {
//执行删除
win.removeIfPossible();
return;
}
mEmbeddedWindowController.remove(client);
}
}
- 从WMS中获取
WindowState
final HashMap mWindowMap = new HashMap<>();
final WindowState windowForClientLocked(Session session, IWindow client, boolean throwOnError) {
return windowForClientLocked(session, client.asBinder(), throwOnError);
}
final WindowState windowForClientLocked(Session session, IBinder client, boolean throwOnError) {
WindowState win = mWindowMap.get(client);
if (DEBUG) Slog.v(TAG_WM, "Looking up client " + client + ": " + win);
if (win == null) {
if (throwOnError) {
throw new IllegalArgumentException(
"Requested window " + client + " does not exist");
}
ProtoLog.w(WM_ERROR, "Failed looking up window session=%s callers=%s", session,
Debug.getCallers(3));
return null;
}
if (session != null && win.mSession != session) {
if (throwOnError) {
throw new IllegalArgumentException("Requested window " + client + " is in session "
+ win.mSession + ", not " + session);
}
ProtoLog.w(WM_ERROR, "Failed looking up window session=%s callers=%s", session,
Debug.getCallers(3));
return null;
}
return win;
}
- 重置和删除
WindowState
状态
win.removeIfPossible
方法和它的名字一样,并不是直接执行删除操作,而是进行多个条件判断过滤,满足其中一个条件就会return,推迟删除操作。比如View正在运行一个动画,这是就会推迟删除操作知道动画完成。然后调用removeImmediately
方法。
class WindowState extends WindowContainer implements WindowManagerPolicy.WindowState,
InsetsControlTarget {
void removeImmediately() {
super.removeImmediately();
//已经删除
if (mRemoved) {
// Nothing to do.
ProtoLog.v(WM_DEBUG_ADD_REMOVE,
"WS.removeImmediately: %s Already removed...", this);
return;
}
//移除标记
mRemoved = true;
......
final DisplayContent dc = getDisplayContent();
......
//policy做移除操作
dc.getDisplayPolicy().removeWindowLw(this);
//关闭输入事件渠道
disposeInputChannel();
mWinAnimator.destroyDeferredSurfaceLocked();
mWinAnimator.destroySurfaceLocked();
//Session集合冲移除WindowState
mSession.windowRemovedLocked();
.....
//集中处理清除工作
mWmService.postWindowRemoveCleanupLocked(this);
}
}
3、WindowManagerGlobal 相关数据删除
在WindowManagerGlobal方法中,会删除相关的一些数据,如ViewRootImpl、LayoutParams、DecorView,并将DecorView加入到死亡列表中。
WindowManagerGlobal@doRemoveView(...)
void doRemoveView(ViewRootImpl root) {
boolean allViewsRemoved;
synchronized (mLock) {
//从ViewRootImpl获取到索引值
final int index = mRoots.indexOf(root);
if (index >= 0) {
//删除ViewRootImpl列表中的数据
mRoots.remove(index);
//删除LayoutParams列表中的数据
mParams.remove(index);
//删除DecorView列表中的数据
final View view = mViews.remove(index);
//DecorView加入到死亡列表
mDyingViews.remove(view);
}
allViewsRemoved = mRoots.isEmpty();
}
if (ThreadedRenderer.sTrimForeground && ThreadedRenderer.isAvailable()) {
doTrimForeground();
}
if (allViewsRemoved) {
InsetsAnimationThread.release();
}
}