handler机制源码层解析(1)

1.子线程创建handler对象

public class MainActivity extends AppCompatActivity {
    private Handler handler;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        init();
    }

    private void init() {
        new Thread(){
            @Override
            public void run() {
                handler=new Handler();
            }
        }.start();
    }
}
 抛出异常:
  java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
                                                                                         at android.os.Handler.<init>(Handler.java:200)
                                                                                         at android.os.Handler.<init>(Handler.java:114)
                                                                                         at com.example.administrator.handlertest.MainActivity$1.run(MainActivity.java:20)


也就是说在子线程创建handler对象必须先执行Looper.prepare方法,那就从源码上看看这个方法做了什么
   private static void prepare(boolean quitAllowed) {
        if (sThreadLocal.get() != null) {
            throw new RuntimeException("Only one Looper may be created per thread");
        }
        sThreadLocal.set(new Looper(quitAllowed));
    }

这个方法中,有两个重要的步骤。
1.创建了一个Looper对象 
private Looper(boolean quitAllowed) {
        mQueue = new MessageQueue(quitAllowed);
        mThread = Thread.currentThread();
    }
可以看到这个构造方法中,初始化了一个消息队列MessageQueue和当前Threade对象。
2.将Looper对象set进sThreadLocal对象当中。那首先看一下sThreadLocal对象的作用是什么。
ThreadLocal从字面意义上理解是“本地线程”,但实际上并不是用来操作什么本地线程而是用于实现不同线程的数据副本,当使用ThreadLocal维护变量时,它会为每个使用该变量的线程提供独立的变量副本;每一个线程都可以独立地改变自己的副本并且不会影响其他线程所持有的对应的副本。sThreadLocal对象是存在Looper类中的static final对象:
 static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
也就是这个方法的作用是当在某一个Thread中中执行Looper.prepare()方法的时候系统就会将与该Thread所对应的Looper保存到sThreadLocal中,不同的线程对应着不同的Looper,
,但他们均由系统保存在sThreadLocal中,并且互不影响,相互独立,并且可以通过sThreadLocal.get()方法获取不同线程所对应的Looper。

小结:一个线程对应一个Looper对象,一个Looper对象对应一个消息队列,三者一一对应。在子线程创建handler对象的正确步骤:
 new Thread(){
            @Override
            public void run() {
                Looper.prepare();
                handler=new Handler(){
                    @Override
                    public void handleMessage(Message msg) {
                        super.handleMessage(msg);
                    }
                };
                Looper.loop();//开始轮询消息队列
            }
        }.start();





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值