频道栏目
首页 > 资讯 > Android > 正文

Android中的异步消息

17-06-19        来源:[db:作者]  
收藏   我要投稿

Android中的异步消息。上一次简单说了下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()方法就会得到消息,并做出响应的处理。

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

对异步消息的理解:

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

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

Handler,Message,Looper Handler.post() View.post() Activity.runOnUiThread()

tips:

试验证明Handler是可以在它所在的线程中发送消息的。
相关TAG标签
上一篇:block块中引用成员变量引起内存泄漏问题
下一篇:ReactiveX/RxSwift 初见
相关文章
图文推荐

关于我们 | 联系我们 | 广告服务 | 投资合作 | 版权申明 | 在线帮助 | 网站地图 | 作品发布 | Vip技术培训 | 举报中心

版权所有: 红黑联盟--致力于做实用的IT技术学习网站