android消息机制,异步和多线程
前言
在xxxx1.92正式版的时候付费购买曾单独封装了一个流程PaymentFlow并继承于Handler,调用方只要依据这个流程创建流程实例并触发开始,实例即可依据设定的支付流程完成.但在异步和多线程方面却有’ java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()’的问题.最近在作风网络库的替换,网络库使用的Handler的继承类MessageHandler作为回调.同样也存在多线程的异步调用或诸塞的问题,所以在此就将Handler的机制在研究一遍.
1. Handler,Looper,Activity
Android应用程序是消息驱动的,并通过Looper,Handler来实现消息循环机制,且是针对线程的. 一个线程可以存在(当然也可以不存在)一个消息队列和一个消息循环(Looper),特定线程的消息只能分发给本线程,不能进行跨线程,跨进程通讯.但是创建的工作线程默认是没有消息循环和消息队列的,如果想让该线程具有消息队列和消息循环,需要在线程中首先调用Looper.prepare()来创建消息队列,然后调用Looper.loop()进入消息循环. Handler的作用是把消息加入特定的(Looper)消息队列中,并分发和处理该消息队列中的消息.构造Handler的时候可以指定一个Looper对象,如果不指定则利用当前线程的Looper创建.Activity是一个UI线程,运行于主线程中,Android系统在启动的时候会为Activity创建一个消息队列和消息循环(Looper).一个Activity中可以创建多个工作线程或者其他的组件,如果这些线程或者组件把他们的消息放入Activity的主线程消息队列,那么该消息就会在主线程中处理了.之间的关系如下图所示
我们可以写个测试用例在Activity和Handler中分别打印出线程编号就明白在默认情况下(例如: private Handler handler = new Handler();),Activity和Handler是在同个线程上运行的.
如果一个线程中调用Looper.prepare(),那么系统就会自动的为该线程建立一个消息队列,然后调用 Looper.loop();之后就进入了消息循环,这个之后就可以发消息、取消息、和处理消息.这个如何发送消息和如何处理消息可以在其他的线程中通过Handle来做,但前提是我们的Hanle知道这个子线程的Looper,但是你如果不是在子线程运行 Looper.myLooper(),一般是得不到子线程的looper的.
除此也可以通过创建HandlerThread来为Handler来创建一个新得的Looper并赋予Handler,这样Handler就会在非主线程执行.
HandlerThread thread=new HandlerThread(“handler_thread”));
thread.start();
Handler m=new Handler(thread.getLooper());
2. Handler与Thread的区别
Handler与调用者处于同一线程,如果Handler里面做耗时的动作,调用者线程会阻塞.Android UI操作不是线程安全的,并且这些操作必须在UI线程中执行.Android提供了几种基本的可以在其他线程中处理UI操作的方案,包括Activity 的runOnUiThread(Runnable),View的post以及1.5版本的工具类AsyncTask等方案都采用了 Handler,Handler的post对线程的处理也不是真正start一个新的线程,而是直接调用了线程的run方法.
3. Handler对于Message的处理不是并发的
一个Looper 只有处理完一条Message才会读取下一条,所以消息的处理是阻塞形式的.但是如果用不同的Looper则能达到并发的目的.Service 中,onStart的执行也是阻塞的.如果一个startService在onStart执行完成之前,再次条用startService也会阻塞.如果希望能尽快的执行onStart则可以在onStart中使用handler,因为Message的send是非阻塞的.如果要是不同消息的处理也是并发 的,则可以用不同的Looper实例化Handler.
4. 资源回收
向Handler对象发送类似new Message()形式的空Message可以达到清空Message的目的,这种做法与getLooper().quit()的做法是一样的.如果利用的资源较多,应及时清理.
来源:oschina
链接:https://my.oschina.net/u/57046/blog/76303