基础五:一些重要方法的解释

    @Nullable
    public abstract Intent registerReceiver(@Nullable BroadcastReceiver receiver,
                                            IntentFilter filter);

在主activity线程中注册一个BroadcastReceiver,该广播接收者会被任意匹配intentfilter的Broadcast在主应用程序线程中唤醒

    @Nullable
    public abstract Intent registerReceiver(BroadcastReceiver receiver,
            IntentFilter filter, @Nullable String broadcastPermission,
            @Nullable Handler scheduler);

给这个广播接收者添加权限,这样只有具有同样权限的广播才能触发这个广播接收者,同时该方法可以通过最后一个参数scheduler来修改接收者所在线程位置,如果scheduler不为null,则会识别handler所在线程位置去处理接收者接收到的消息;如果handler为null,则接收者将在主线程

3: new Handler();
该构造函数调用的是Handler(Callback callback, boolean async)方法,只不过第一个参数为null,第二个参数为false,表示
创建一个和当前线程绑定的handler,如果当前线程没有looper,则不会收发消息,并会抛出一个异常

4: new Handler(Looper looper, Callback callback);
该构造函数调用的是Handler(Looper looper, Callback callback, boolean async),只不过第三个参数为false,表示
使用参数中的looper,并使用callback来进行收发消息,样例代码如下

    private final Handler.Callback mHandlerCallback = new Handler.Callback() {
        @Override
        public boolean handleMessage(Message msg) {


                return true;
            }
        }
    };

mHandler = new Handler(looper, mHandlerCallback);

5:Handler(Callback callback, boolean async)
使用当前的线程的looper的callback去处理消息,async表示是同步处理还是异步处理消息

6:Handler(Looper looper, Callback callback, boolean async)
使用当前的Looper,并使用callback去处理消息,async表示是同步处理还是异步处理消息

关于Handler构造函数的总结:
       在handler的构造函数中,均会调用其他构造方法;在最后的构造中,都会用到async这个值,async的值表示Handler处理消息的能力是同步的还是异步;在默认的Handler构造中,默认是同步处理消息的,即当handleMessage处理完一条消息之后,才会接着处理另外一条消息;
       那这里的async为true的时候,表示handler是异步的是用在哪里尼
在我们通常的做法中,通过handler发消息来更新UI,我们也称之为异步处理消息,当此时的async的值是false,表示消息发送是同步的;当async的值为true的时候,主要使用场景如下:

为了让View能够有快速的布局和绘制,android中定义了一个Barrier的概念,当View在绘制和布局时会向Looper中添加了Barrier(监控器),这样后续的消息队列中的同步的消息将不会被执行,以免会影响到UI绘制,但是只有异步消息才能被执行。 所谓的异步消息也只是体现在这,添加了Barrier后,消息还可以继续被执行,不会被推迟运行。

解释如下:
       当ViewRootImpl开始measure和layout ViewTree时,会向主线程的Handler添加Barrier

//scheduleTraversals()方法都会在requestLayout时会被调用
    void scheduleTraversals() {
        if (!mTraversalScheduled) {
            mTraversalScheduled = true;
            mTraversalBarrier = mHandler.getLooper().getQueue().postSyncBarrier();
            mChoreographer.postCallback(
                    Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);
            if (!mUnbufferedInputDispatch) {
                scheduleConsumeBatchedInput();
            }
            notifyRendererOfFramePending();
            pokeDrawLockIfNeeded();
        }
    }

    void unscheduleTraversals() {
        if (mTraversalScheduled) {
            mTraversalScheduled = false;
            mHandler.getLooper().getQueue().removeSyncBarrier(mTraversalBarrier);
            mChoreographer.removeCallbacks(
                    Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);
        }
    }

问题一:
       当一个activity正在绘制界面,此时通过handler来更新界面,这个操作能够成功吗?
如果不能成功,该如何操作;
这个操作不能成功,如果想成功,则构建一个异步的Handler即可

问题二:
       如何避免在创建Handler的时候出现的内存泄漏
当handler类为内部类的时候,会持有对外部类的引用,
为了避免泄露这个外部类,应该将Handler声明为static嵌套类,并且使用对外部类的弱应用。

        static class MyHandler extends Handler {
                WeakReference<MyActivity> mActivity;

                MyHandler(MyActivity activity) {
                        mActivity = new WeakReference<MyActivity>(activity);
                }

                @Override
                public void handleMessage(Message msg) {

                }
        };

当时使用弱引用,会出现空指针的情况,那最好的解决方式为:将handler抽取为外部单独的类,并对activity做判空处理

        public class MyHandler extends Handler {
                WeakReference<MyActivity> mActivity;

                MyHandler(MyActivity activity) {
                        mActivity = new WeakReference<MyActivity>(activity);
                }

                @Override
                public void handleMessage(Message msg) {
                     MyActivity activity = mActivity.get();
      if(activity == null)
         return;   
                }
        };

那有没有更为简洁的方式尼,答案是有的

private Handler myHandler = new Handler(new Handler.Callback() {  

       @Override  
       public boolean handleMessage(Message msg) {  
           return false;  
       }  
   }); 

因为这种方式不存在匿名内部类,而非静态的内部类和匿名内部类都会隐式地持有其外部类的引用,静态的内部类不会持有外部类的引用

问题三:

Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            //do something
            super.handleMessage(msg);
        }
    };
Handler handler = new Handler(new Handler.Callback() {
        @Override
        public boolean handleMessage(Message msg) {
            //do something
            return true;
        }
    });

为什么第一种是匿名内部类,而第二种不是匿名内部类
       匿名内部类就是没有名字的局部内部类,不使用关键字class, extends, implements, 没有构造方法;在第一种实现中,直接new handler类,并实现handleMessage方法,因此是匿名内部类;而在第二种实现中,传递了一个参数,完成了Handler的构造函数,因此其不是匿名内部类

猜你喜欢

转载自blog.csdn.net/yi_master/article/details/78977701