5.4.3 Looper和Handler的同步关系

Looper和Handler会有什么同步关系呢?它们之间确实有同步关系,而且如果不注意此关系,定会铸成大错!

同步关系肯定与多线程有关,我们来看下面的一个例子:

[—>例子2]


//先定义一个LooperThread类

class LooperThread extends Thread{

public Looper myLooper=null;//定义一个public的成员myLooper,初值为空。

public void run(){//假设run在线程2中执行

Looper.prepare();

//myLooper必须在这个线程中赋值

myLooper=Looper.myLooper();

Looper.loop();

}

}

//下面这段代码在线程1中执行,并且会创建线程2

{

LooperThread lpThread=new LooperThread;

lpThread.start();//start后会创建线程2

Looper looper=lpThread.myLooper;//<======注意

//thread2Handler和线程2的Looper挂上钩

Handler thread2Handler=new Handler(looper);

//sendMessage发送的消息将由线程2处理

threadHandler.sendMessage(……)

}


上面这段代码的目的很简单:

线程1中创建线程2,并且线程2通过Looper处理消息。

线程1中得到线程2的Looper,并且根据这个Looper创建一个Handler,这样发送给该Handler的消息将由线程2处理。

但很可惜,上面的代码是有问题的。如果我们熟悉多线程,就会发现标有“注意”的那行代码存在着严重问题。myLooper的创建是在线程2中,而looper的赋值在线程1中,很有可能此时线程2的run函数还没来得及给myLooper赋值,这样线程1中的looper将取到myLooper的初值,也就是looper等于null。另外,


Handler thread2Handler=new Handler(looper)不能替换成

Handler thread2Handler=new Handler(Looper.myLooper())


这是因为,myLooper返回的是调用线程的Looper,即Thread1的Looper,而不是我们想要的Thread2的Looper。

对这个问题,可以采用同步的方式进行处理。你是不是有点迫不及待地想完善这个例子了?其实Android早就替我们想好了,它提供了一个HandlerThread来解决这个问题。