Android 4.2 SetContentView 流程分析(二)
2013-01-02 16:40
316 查看
(2)
(2-1)
由(2-1-1)跟(2-1-2)的分析, 可以知道ViewRootImpl利用Binder机制将WindowManagerService 和 DecoreView建立一个session. 接下来继续分析(2-2) root.setView的流程
(2-2)
(2-2-2)
我们在前面知道sWindowSession 是由ViewRootImpl 和WindowManagerService 所建立出来的一个Session. 所以实做可以去Session 中找.
[ActivityThread.java] final void handleResumeActivity(IBinder token, boolean clearHide, boolean isForward, boolean reallyResume) { //1. 藉由所传入的token跟clearHide信息执行Resume state的流程之后取 //得ActivityClientRecord物件. ActivityClientRecord r = performResumeActivity(token, clearHide); if (r != null) { //2. 由所得到的ActivityClientRecord取得activity对象 final Activity a = r.activity; //... if (r.window == null && !a.mFinished && willBeVisible) { r.window = r.activity.getWindow(); //3. 取得前面所建立的DecoreView View decor = r.window.getDecorView(); decor.setVisibility(View.INVISIBLE); //4. 取得前面所建立的 WindowManagerImpl ViewManager wm = a.getWindowManager(); WindowManager.LayoutParams l = r.window.getAttributes(); a.mDecor = decor; //5. 设定WindowManager.LayoutParams的属性. l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION; l.softInputMode |= forwardBit; if (a.mVisibleFromClient) { a.mWindowAdded = true; //6. 利用WindowManagerImpl依照 //WindowManager.LayoutParams的属性来为DecoreView增加一个 //view的纪录. wm.addView(decor, l); } } else if (!willBeVisible) { //当Activity是处于Invisible state时,就将ActivityClientRecord物件的 //hideForNow属性设定为true.代表目前的window是不可见的. r.hideForNow = true; } } else { // 只要在resume state中一发生exception就马上终止activity的lifecycle. } }这一段程序代码带出了一个关键程序代码,wm.addView , 就由addView 这个function开始分析
[WindowManagerImpl.java] @Override public void addView(View view, ViewGroup.LayoutParams params) { // private final WindowManagerGlobal mGlobal = //WindowManagerGlobal.getInstance(); 是一个singleton的物件. mGlobal.addView(view, params, mDisplay, mParentWindow); } [WindowManagerGlobal.java] public void addView(View view, ViewGroup.LayoutParams params, Display display, Window parentWindow) { //1. 检查传入的参数是否有值,没有的话就发生exception. 保护之后 //的流程出错.是属于一种保护式程序设计. 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); } ViewRootImpl root; View panelParentView = null; //2. 开始进入lock阶段以保护以下流程一次只能有一个thread执行或 //是确保执行流程一定要完成才能再次的执行. synchronized (mLock) { //3. 启动监控者只要用来监控系统属性变化 //4. 建立一个新的ViewRootImpl对象 root = new ViewRootImpl(view.getContext(), display); (2-1) //5. 设定View的layout参数,这里的View是DecoreView, layout //参数是handleResumeActivity函数中第五个步骤的 //WindowManager.LayoutParams 属性设定. view.setLayoutParams(wparams); //... } try { //6. 利用ViewRootImpl对象来设定目前的画面. root.setView(view, wparams, panelParentView); (2-2) } catch (RuntimeException e) { //一发生exception,马上清理目前相关View资源 } }
(2-1)
[ViewRootImpl.java] public ViewRootImpl(Context context, Display display) { //... //详见以下分析(2-1-1) // final IWindowSession mWindowSession; mWindowSession = WindowManagerGlobal.getWindowSession(context.getMainLooper()); //... //详见以下分析(2-1-2) //final W mWindow; mWindow = new W(this); }(2-1-1)
[WindowManagerGlobal.java] public static IWindowSession getWindowSession(Looper mainLooper) { synchronized (WindowManagerGlobal.class) { if (sWindowSession == null) { try { //1. 由Main looper取得 InputMethodManager对象. InputMethodManager imm = InputMethodManager.getInstance(mainLooper); //2. 取得WindowManagerService的Proxy. IWindowManager windowManager = getWindowManagerService(); //3. 利用WindowManagerService Proxy去开启Session. //此session的建立目的是将WindowManagerService和 //InputMethodManager的inputContext(DecoreView) //作IPC (Binder),之后得到session的handler. sWindowSession = windowManager.openSession( imm.getClient(), imm.getInputContext()); float animatorScale = windowManager.getAnimationScale(2); ValueAnimator.setDurationScale(animatorScale); } catch (RemoteException e) { Log.e(TAG, "Failed to open window session", e); } } return sWindowSession; } }(2-1-2)
[ViewRootImpl.java] static class W extends IWindow.Stub { private final WeakReference<ViewRootImpl> mViewAncestor; private final IWindowSession mWindowSession; W(ViewRootImpl viewAncestor) { //这里只有将ViewRootImpl参考对象转成一个软对象参考 //mViewAncestor, 除了方便作GC处理,其他就没甚么用处了, 在 //JAVA中的对象参考有分四个类别.都是跟GC有关的.祥建请参 //考Java书籍. mViewAncestor = new WeakReference<ViewRootImpl>(viewAncestor); mWindowSession = viewAncestor.mWindowSession; } //... }
由(2-1-1)跟(2-1-2)的分析, 可以知道ViewRootImpl利用Binder机制将WindowManagerService 和 DecoreView建立一个session. 接下来继续分析(2-2) root.setView的流程
(2-2)
[ViewRootImpl.java] public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) { //第一个 view的参数是一个 DecoreView //... //保存 mView = view; //... //在View加入Windows Manager service前先排程第一个Layout,目的 //用来确保从系统接收到其他新的event之前可以做session的relayout //功能. requestLayout(); (2-2-1) //... //详见以下分析 res = sWindowSession.add(mWindow, mSeq, mWindowAttributes, getHostVisibility(), mAttachInfo.mContentInsets, mInputChannel); (2-2-2) //... } (2-2-1) public void requestLayout() { checkThread(); mLayoutRequested = true; scheduleTraversals(); } void scheduleTraversals() { if (!mTraversalScheduled) { mTraversalScheduled = true; //停止后续的消息处理功能 mTraversalBarrier = mHandler.getLooper().postSyncBarrier(); // Choreographer设置了CALLBACK类型为TRAVERSAL的处理对象, //即mTraversalRunnable.Choreographer 是Android 4.1之后才有 //的新类别,主要的功用是用来处理视讯不流畅的问题. mChoreographer.postCallback( Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null); scheduleConsumeBatchedInput(); } } final class TraversalRunnable implements Runnable { @Override public void run() { doTraversal(); } } void doTraversal() { if (mTraversalScheduled) { mTraversalScheduled = false; //恢复后续的所有讯息事件处理. mHandler.getLooper().removeSyncBarrier(mTraversalBarrier); if (mProfile) { Debug.startMethodTracing("ViewAncestor"); } Trace.traceBegin(Trace.TRACE_TAG_VIEW, "performTraversals"); try { //开始布局并且绘画显示画面. performTraversals(); } finally { Trace.traceEnd(Trace.TRACE_TAG_VIEW); } if (mProfile) { Debug.stopMethodTracing(); mProfile = false; } } }
(2-2-2)
我们在前面知道sWindowSession 是由ViewRootImpl 和WindowManagerService 所建立出来的一个Session. 所以实做可以去Session 中找.
[Session.java] public int add(IWindow window, int seq, WindowManager.LayoutParams attrs, int viewVisibility, Rect outContentInsets, InputChannel outInputChannel) { // final WindowManagerService mService; return mService.addWindow(this, window, seq, attrs, viewVisibility, outContentInsets, outInputChannel); } [WindowManagerService.java] public int addWindow(Session session, IWindow client, int seq, WindowManager.LayoutParams attrs, int viewVisibility, Rect outContentInsets, InputChannel outInputChannel) { //1. 检查layout属性是否为layout window type. int res = mPolicy.checkAddPermission(attrs); if (res != WindowManagerImpl.ADD_OKAY) { return res; } WindowState attachedWindow = null; WindowState win = null; //... //2. 新增一个 WindowState类型对象. win = new WindowState(this, session, client, token, attachedWindow, seq, attrs, viewVisibility); res = WindowManagerImpl.ADD_OKAY; //... //3. 详见分析如下: win.attach(); // mWindowMap是一个hash table,其形态如下: // final HashMap<IBinder, WindowState> mWindowMap //4. 将新产生的WindowState搭配一个新的IBinder放入Hash table mWindowMap.put(client.asBinder(), win); //… Binder.restoreCallingIdentity(origId); return res; } [WindowState.java] void attach() { //mSession 保存的是一个 sWindowSession对象. 在建构 //WindowState 对象就保存了. mSession.windowAddedLocked(); } [Session.java] void windowAddedLocked() { if (mSurfaceSession == null) { //1. 详见分析如下 mSurfaceSession = new SurfaceSession(); //2. 利用STL中的set观念来记录SurfaceSession被产生了几次. //用来确保每增加一次Window就会有一个SurfaceSession来控制. mService.mSessions.add(this); } mNumWindow++; } [SurfaceSession.java] /** Create a new connection with the surface flinger. */ public SurfaceSession() { mNativeClient = nativeCreate(); // nativeCreate是一个 native function. } private static native int nativeCreate();
相关文章推荐
- Android 4.2 SetContentView 流程分析(一)
- Android 4.2 setContentView 流程研究分析
- Android 4.2 SetContentView 流程分析(三)
- android应用程序窗口框架学习(2)-view绘制流程源代码解析-setContentView与LayoutInflater加载解析机制源码分析
- 从setContentView方法分析Android加载布局流程
- 从setContentView方法分析Android加载布局流程
- 从setContentView方法分析Android加载布局流程
- 从setContentView分析Android加载布局的流程
- Android中将布局文件/View添加至窗口过程分析 ---- 从setContentView()谈起
- 【转载】Android中将布局文件/View添加至窗口过程分析 ---- 从setContentView()谈起
- Android应用setContentView与LayoutInflater加载解析机制源码分析(超级棒!)
- Android中将布局文件/View添加至窗口过程分析 ---- 从setContentView()谈起
- Android中将布局文件/View添加至窗口过程分析 ---- 从setContentView()谈起
- Android应用setContentView与LayoutInflater加载解析机制源码分析
- Android中将布局文件/View添加至窗口过程分析 ---- 从setContentView()谈起
- Android应用setContentView与LayoutInflater加载解析机制源码分析
- Android应用setContentView与LayoutInflater加载解析机制源码分析
- Android中将布局文件/View添加至窗口过程分析 ---- 从setContentView()谈起(写的很好,这个不是从启动app说的,说的是UI是怎么绘制的)
- Android应用setContentView与LayoutInflater加载解析机制源码分析
- Android中将布局文件/View添加至窗口过程分析 ---- 从setContentView()谈起