Activity界面的添加与删除
来源:互联网 发布:origin8软件 编辑:程序博客网 时间:2024/05/21 14:54
安卓中是由WindowManagerService来管理所有的窗口,下面来看下Activity是如何与WindowManagerService交互,控制应用界面的添加与删除的
Activity界面的添加
我们通常都是在onCreate方法中调用setContentView来设置布局,此时只是完成了视图树的创建,并没有通知WindowManagerService添加界面,真正添加界面是在回调完onResume完成的
我们的Activity都是在ActivityThread中创建,并回调Activity的各种生命周期的,调用onResume的方法为handleResumeActivity
final void handleResumeActivity(IBinder token, boolean clearHide, boolean isForward, boolean reallyResume, int seq, String reason) { ActivityClientRecord r = mActivities.get(token); ...... r = performResumeActivity(token, clearHide, reason); ...... if (r.activity.mVisibleFromClient) { r.activity.makeVisible(); } ...... }
在handleResumeActivity中是通过performResumeActivity完成Activity的onResume回调的,之后会调用Activity的makeVisible方法
void makeVisible() { if (!mWindowAdded) { ViewManager wm = getWindowManager(); wm.addView(mDecor, getWindow().getAttributes()); mWindowAdded = true; } mDecor.setVisibility(View.VISIBLE); }
如果界面没有被添加,就调用ViewManager的addView方法
ViewManager是一个接口,在这里它是指WindowManagerImpl类,看下他的addView方法
public void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params) { applyDefaultToken(params); mGlobal.addView(view, params, mContext.getDisplay(), mParentWindow); }
其中mGlobal是一个WindowManagerGlobal对象,而且他本身是一个单例
private final WindowManagerGlobal mGlobal = WindowManagerGlobal.getInstance();
接着看WindowManagerGlobal的addView方法
public void addView(View view, ViewGroup.LayoutParams params, Display display, Window parentWindow) { ...... ViewRootImpl root; ...... root = new ViewRootImpl(view.getContext(), display); view.setLayoutParams(wparams); mViews.add(view); mRoots.add(root); mParams.add(wparams); root.setView(view, wparams, panelParentView);}
逻辑也很简单,就是先判断参数的正确性,接着创建一个ViewRootImpl对象,然后将数据添加到数组中,最后调用ViewRootImpl的setView方法,接着去看setView方法
public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) { ...... res = mWindowSession.addToDisplay(mWindow, mSeq, mWindowAttributes, getHostVisibility(), mDisplay.getDisplayId(), mAttachInfo.mContentInsets, mAttachInfo.mStableInsets, mAttachInfo.mOutsets, mInputChannel); ...... }
代码有点长,但是重要的也就是上面这句,调用mWindowSession的addToDisplay方法
mWindowSession是一个IWindowSession对象,他是在ViewRootImpl的构造方法中被创建的
mWindowSession = WindowManagerGlobal.getWindowSession();
可以看到他也是一个单例
public static IWindowSession getWindowSession() { synchronized (WindowManagerGlobal.class) { if (sWindowSession == null) { try { InputMethodManager imm = InputMethodManager.getInstance(); IWindowManager windowManager = getWindowManagerService(); 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")); try { sWindowManagerService = getWindowManagerService(); ValueAnimator.setDurationScale(sWindowManagerService.getCurrentAnimatorScale()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } return sWindowManagerService; } }
可以看到mWindowSession是由WindowManagerService调用openSession方法创建的,且每一个应用只有一个mWindowSession对象,而且他还是一个binder,我们的应用通过它可以与WindowManagerService交互
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; }
回到setView方法,看看mWindowSession,也就是Session的addToDisplay干了什么
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); }
其中mService就是WindowManagerService,方法addWindow也很明显就是将我们的窗口添加进来
以上就实现了我们Activity界面的添加,接着看看Activity界面是如何被删除的
Activity界面的删除
Activity界面的添加是在执行完onResume后完成的,而Activity界面被删除则是在执行完onDestroy后完成的(注意我这里说的删除不是不可见)
ActivityThread调用onDestroy的方法为handleDestroyActivity
private void handleDestroyActivity(IBinder token, boolean finishing, int configChanges, boolean getNonConfigInstance) { ActivityClientRecord r = performDestroyActivity(token, finishing, configChanges, getNonConfigInstance); ...... wm.removeViewImmediate(v); ...... }
回调onDestroy是由performDestroyActivity完成的,之后会调用WindowManager的removeViewImmediate方法,参数v就是Activity对应的布局,也就是顶层的View : DecorView,wm也就是我们前面说的WindowManagerImpl
public void removeViewImmediate(View view) { mGlobal.removeView(view, true); }
还是调用了WindowManagerGlobal的removeView方法
public void removeView(View view, boolean immediate) { if (view == null) { throw new IllegalArgumentException("view must not be null"); } synchronized (mLock) { int index = findViewLocked(view, true); View curView = mRoots.get(index).getView(); removeViewLocked(index, immediate); if (curView == view) { return; } throw new IllegalStateException("Calling with view " + view + " but the ViewAncestor is attached to " + curView); } }private void removeViewLocked(int index, boolean immediate) { ViewRootImpl root = mRoots.get(index); View view = root.getView(); 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); } } }
可以看到又调用了removeViewLocked方法,然后根据传递进来的View找到对应的ViewRootImpl对象,然后调用ViewRootImpl的die方法,参数immediate为true
boolean die(boolean immediate) { // Make sure we do execute immediately if we are in the middle of a traversal or the damage // done by dispatchDetachedFromWindow will cause havoc on return. if (immediate && !mIsInTraversal) { doDie(); return false; } if (!mIsDrawing) { destroyHardwareRenderer(); } else { Log.e(mTag, "Attempting to destroy the window while drawing!\n" + " window=" + this + ", title=" + mWindowAttributes.getTitle()); } mHandler.sendEmptyMessage(MSG_DIE); return true; }
又执行到了doDie上
void doDie() { ...... dispatchDetachedFromWindow(); ...... }
起作用的是dispatchDetachedFromWindow方法
void dispatchDetachedFromWindow() { ...... mWindowSession.remove(mWindow); ...... }
mWindowSession之前说过是专门和WindowManagerService交互的
public void remove(IWindow window) { mService.removeWindow(this, window); }
Session对象又调用了WindowManagerService的removeWindow方法,之后的工作就交给了WindowManagerService完成
如此就实现了Activity界面的删除
- Activity界面的添加与删除
- 快捷方式的添加与删除
- 路由的添加与删除
- Cookie 的添加与删除
- Cookie 的添加与删除
- 用户信息的添加与删除
- 一个自动添加Activity以及删除的ActivityManager管理器
- 默认共享的添加与删除策略
- 多行添加与删除的实现
- JList的修改、删除与添加
- mysql 外键的添加与删除
- ORACEL的多列添加与删除
- js仿数据库的添加与删除
- VBA 工作表的添加与删除
- dom节点的添加与删除
- ASM磁盘的添加与删除
- vector顺序容器的添加与删除
- libevent中事件的添加与删除
- Kotlin之let,apply,with,run函数区别
- 汉字和笔画数
- 正确使用MySQL JDBC setFetchSize()方法解决JDBC处理大结果集 java.lang.OutOfMemoryEr
- Android:自定义Dialog上面的黑框或者说是Title怎么去掉
- oracle 9i与11g 服务端tnsping与sqlplus命令的使用的一些差异
- Activity界面的添加与删除
- Spring MVC 环境搭建(一)
- 进程间的通信方式
- 区块链MerkleTree算法实现
- Java多线程系列--“JUC锁”06之 Condition条件
- initcall机制
- 确定opencv矩阵数据类型
- swing 下拉菜单
- 构造函数 课堂练习3: