View之Handler的应用

2019-12-17  本文已影响0人  钦_79f7

View中Handler的应用

==问题==:View中mHandler实例是如何复用?在整个布局中所有的View都持有同一个View Handler么?还是同一个Activity下持有同一个实例?

  1. android.view.View中有成员方法post(Runnable),其实质就是通过Handler的post方法,进行消息传递。通过包属性mAttachInfo持有的mHandler.post();

    /**
     * <p>Causes the Runnable to be added to the message queue.
     * The runnable will be run on the user interface thread.</p>
     * 
     * @param action The Runnable that will be executed.
     *
     */
    public boolean post(Runnable action) {
        final AttachInfo attachInfo = mAttachInfo;
        if (attachInfo != null) {
            return attachInfo.mHandler.post(action);
        }
        // Postpone the runnable until we know on which thread it needs to run.
        // Assume that the runnable will be successfully placed after attach.
        getRunQueue().post(action);
        return true;
    }
    AttachInfo mAttachInfo;
    
  2. AttachInfo,是View中的一个静态内部类,是View相关信息的存储集合,其中就有mHandler属性。

    /**//View中的静态内部类
     * A set of information given to a view when it is attached to its parent
     * window.
     */
    final static class AttachInfo {
        /**
         * A Handler supplied by a view's {@link android.view.ViewRootImpl}. This
         * handler can be used to pump events in the UI events queue.
         */
        final Handler mHandler;
    }
    
  3. View的mAttachInfo属性是在View的包成员方法dispatchAttachedToWindow()中被赋值的。

    /**
     * @param info the {@link android.view.View.AttachInfo} to associated with
     *        this view
     */
    void dispatchAttachedToWindow(AttachInfo info, int visibility) {
        mAttachInfo = info;
        ...
    }
    
  4. android.view.ViewRootImpl中有performTraversals(),通过host调用了View的dispatchAttachedToWindow方法,同时也为View传入了mAttachInfo对象,其中此方法的调用是在doTraversal()中进行的,同时也因为performTraversals()是私有方法,要想外部调用只能在别处有引用才能起作用。

    View mView;
    private void performTraversals() {
    // cache mView since it is used so much below...
        final View host = mView;
        ...
        host.dispatchAttachedToWindow(mAttachInfo, 0);
        ...
    }
    void doTraversal() {
        if (mTraversalScheduled) {
            mTraversalScheduled = false;
            mHandler.getLooper().getQueue().removeSyncBarrier(mTraversalBarrier);
    
            if (mProfile) {
                Debug.startMethodTracing("ViewAncestor");
            }
    
            performTraversals();
    
            if (mProfile) {
                Debug.stopMethodTracing();
                mProfile = false;
            }
        }
    }
    
    final class TraversalRunnable implements Runnable {
        @Override
        public void run() {
            doTraversal();
        }
    }
    final TraversalRunnable mTraversalRunnable = new TraversalRunnable();
    
  5. android.view.ViewRootImpl,在构造器中就进行View.AttachInfo的初始化,并将mHandler对象传入,其中mHandler的实际类型是包权限内部类ViewRootHandler。

    public ViewRootImpl(Context context, Display display) {
        mContext = context;
        ...
        mAttachInfo = new View.AttachInfo(mWindowSession, mWindow, display, this, mHandler, this);
        ...
    }
    //初始化mHandler
    final ViewRootHandler mHandler = new ViewRootHandler();
    //ViewRootHandler是ViewRootImpl的一个内部类
    final class ViewRootHandler extends Handler {}
    
  6. ViewRootImpl中方法setView,为其属性View mView 赋值

    /**
     * We have one child
     */
    public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {
        synchronized (this) {
            if (mView == null) {
                mView = view;
                ...
            }
        }
    }
    
上一篇 下一篇

猜你喜欢

热点阅读