ViewTreeObserver 以及CopyOnWriteAr

2018-04-25  本文已影响0人  lurenjia

ViewTreeObserver 视图树观察者,当视图树进行测量,布局,焦点,绘制等情况时,视图树ViewTreeObserver都会收到通知,回调相应的方法。
这个对象不用我们自己实例化,直接从view中获取。


        ViewTreeObserver observer = root.getViewTreeObserver();
        observer.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                int[] location = new int[2];
                root.getLocationInWindow(location);
                int[] location1 = new int[2];
                root.getLocationOnScreen(location1);

                Log.i(TAG, "locationX: " + location[0]);
                Log.i(TAG, "locationY: " + location[1]);
                Log.i(TAG, "location1X: " + location1[0]);
                Log.i(TAG, "location1Y: " + location1[1]);
                
                observer.removeOnGlobalLayoutListener(this);
            }
        });

这个有什么用呢,比如说我们要获取某一个控件的宽度,在onCreate方法是获取不到的,这个时候就可以用这个ViewTreeObserver这个视图观察者来搞了,等视图测量完或者布局完就可以拿宽高了。用完了记得remove掉这个视图。当然我们也可以在onResume中拿到这个宽高

其实他的内部是把你设置的listener都放到了一个个的list中(CopyOnWriteArrayList),每次回调都会遍历这个list然后回调其中的方法。
说道这个CopyOnWriteArrayList这个东西是写时复制容器。 我们使用ArrayList进行并发操作就可能会抛异常,使用CopyOnWriteArrayList就不会,因为他在写的时候进行了加锁,并对原来的元素进行一次copy,所以写的时候是在copy的元素上进行的写然后在将原来的元素指针指向这个copy的元素,所以对于并发来说不影响读,当然可能可能没有那么的即时。

 public boolean add(E e) {
        synchronized (lock) {
            Object[] elements = getArray();
            int len = elements.length;
            Object[] newElements = Arrays.copyOf(elements, len + 1);
            newElements[len] = e;
            setArray(newElements);
            return true;
        }
    }

其实这个鬼还有一个缺点就是占用内存,因为毕竟进行了一次copy。

这个东西适合并发情况下读多写少的场景,毕竟占用一个双倍的内存其实也是一个很大的问题的。

上一篇下一篇

猜你喜欢

热点阅读