Android中的异步消息

来源:互联网 发布:淘宝手机配件店铺名字 编辑:程序博客网 时间:2024/06/15 03:00

最近有两门课要交课程设计,手头也有一大堆实验要做,健身还不能停,真是忙的一比。

上一次简单说了下AsyncTask,今天说一点稍微深入的东西,即AsyncTask的原理。

class MyThread extends Thread {    public Handler mHandler;    public void run() {        Looper.prepare();        mHandler = new Handler() {            public void handleMessage(Message msg) {                //process incoming messages here            }        };        Looper.loop();    }    } 

以上是一个标准的包含异步消息循环线程,分别干了以下几件事:
1. 使用Looper.prepare();为当前线程创建一个与之绑定的Looper。同时也创建了一个MessageQueue。
2. 创建该线程的Handler。
3. 调用Looper.loop();方法开启消息循环,不断地从消息队列中取消息。

经过以上三步,该线程内就有了一个消息循环,使用该线程的Handler在其他线程发送消息到本线程的MessageQueue中,上面的handlerMessage()方法就会得到消息,并做出响应的处理。

用通俗点的语言来讲就是,我们要先准备一个消息循环的通道,然后再准备好消息来了之后我们要进行的处理。最后开启消息循环,让这个消息通道运转起来。经过这三步的准备,我们就可以开始去别的线程向该线程发消息了。

对异步消息的理解:

  1. Handler、MessageQueue、Looper三者和线程绑定。一个线程只能有一个Looper和一个MessageQueue,但是可以有多个Handler的。不同的Handler在非绑定线程中将消息发送到创建他的线程的MessageQueue中。至于怎么实现的,这是因为Handler在发送消息的时候会去ThreadLocal中寻找本身绑定线程所关联的MessageQueue,并且将消息往这个队列中发送,所以实现了从其他线程发送消息到本线程。有点像卧底在敌方内部得到消息后发往我方的意思。
  2. 创建Hanlder的时候会去寻找当前线程的Looper,调用Looper.myLooper().该方法会去ThreadLocal中寻找该线程对应的Looper对象,如果找不到则会出错。而该对象正是之前调用Looper.prepare()时set进ThreadLocal的。
  3. Message有三个字段用来携带简单的数据,也可以用setData()发送一个Bundler对象,或直接使用obj字段传递任意对象。
  4. 对于Message对象,一般并不推荐直接使用它的构造方法得到,而是建议通过使用Message.obtain()这个静态的方法或者Handler.obtainMessage()获取。Message.obtain()会从消息池中获取一个Message对象,如果消息池中是空的,才会使用构造方法实例化一个新Message,这样有利于消息资源的利用。并不需要担心消息池中的消息过多,它是有上限的,上限为10个。Handler.obtainMessage()具有多个重载方法,如果查看源码,会发现其实Handler.obtainMessage()在内部也是调用的Message.obtain()。
  5. 线程和Handler不是一起出现的!。子线程是可以没有Handler的,Handler是用来发送和处理消息的,而不是所有的线程都需要发送和处理消息,有的线程只进行运算,不发送消息。
  6. 不要误会Runnable == 线程。实际上Runnable只是一种action。同样我们可以将这种action使用Handler.post()出去,这样就不用复写Handler的handleMessage()方法了。

HandlerThread

该类是Android提供的带消息队列的线程类。本质上就是一个普通的Thread,只不过内部自动建立了消息队列。使用这个类可以很方便的生成一个循环的子线程,并且可以轻易实现该线程的循环开关。当然使用for或者while加上线程休眠等,也可以形成一个定时的循环子线程,但是不停的开启关闭子线程会造成比较大的开销。

quit()和quitSafely()

前者会将消息队列中的所有消息移除,而后者只会将消息队列中的延迟消息移除,非延迟的消息会继续派发出去给Handler处理。

HandlerThread的特点

  • HandlerThread将loop转到子线程中处理,说白了就是将分担MainLooper的工作量,降低了主线程的压力,使主界面更流畅。(不太理解)
  • 开启一个线程起到多个线程的作用。处理任务是串行执行,按消息发送顺序进行处理。HandlerThread本质是一个线程,在线程内部,代码是串行处理的。
  • 但是由于每一个任务都将以队列的方式逐个被执行到,一旦队列中有某个任务执行时间过长,那么就会导致后续的任务都会被延迟处理。
  • HandlerThread拥有自己的消息队列,它不会干扰或阻塞UI线程。

对于网络IO操作,HandlerThread并不适合,因为它只有一个线程,还得排队一个一个等着。

四种线程间(与主线程)通信的方法:

  1. Handler,Message,Looper
  2. Handler.post()
  3. View.post()
  4. Activity.runOnUiThread()

tips:

  1. 试验证明Handler是可以在它所在的线程中发送消息的。
原创粉丝点击