Android 4.2 SetContentView 流程分析(二)

(2)

[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();

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值