在非UI线程使用Handler

handler对象所绑定的线程并不取决于该handler对象由哪个线程构建,而是取决于该handler对象所绑定的Looper属于哪个线程。

Looper就像一个消息队列(MessageQueue)的管家,一个消息队列只有一个管家,并且管理者整个消息队列,而一个消息队列内可以容纳多个消息(Message),而工人(Handler)也可以有多个,管家派遣他们向消息队列中存储或取出消息后执行任务;
所以它们的个数如下:

管家(Looper): 1 个;
消息队列(MessageQueue):1 个;
消息(Message):可以多个;
工人(Handler):可以多个;

在非UI线程使用Handler进行线程通信时,一般都需要进行3个步骤:

  • 创建Looper Looper.prepare() (创建了一个Looper和MessageQueue)
  • 创建Handler Handler
  • 启动消息循环 Looper.loop()

如果你不带参数实例化:Handler handler=new Handler();那么这个会默认绑定当前线程的Looper。
一般而言,如果你的Handler是要来刷新操作UI的,那么就要在主线程下跑。有如下情况:

  1. 要刷新UI,handler要用到主线程的looper。那么在主线程Handler handler=new Handler();,如果在其他线程,也要满足这个功能的话,要Handler handler=new Handler(Looper.getMainLooper());
  2. 不用刷新ui,只是处理消息。 当前线程如果是主线程的话,Handler handler = new Handler();不是主线程的话,Looper.prepare(); Handler handler = new Handler();Looper.loop();或者Handler handler = new Handler(Looper.getMainLooper());

若是实例化的时候用Looper.getMainLooper()就表示放到主UI线程去处理。
如果不是的话,因为只有UI线程默认Loop.prepare();Loop.loop();过,其他线程需要手动调用这两个,否则会报错。

Handler通过Message通信的基本方式:

使用Looper.myLooper可以取得当前线程的Looper对象。
使用mHandler = new Handler(Looper.myLooper()); 可产生用来处理当前线程的Handler对象。
使用mHandler = new Handler(Looper.getMainLooper()); 可产生用来处理main线程的Handler对象。

一般子线程发送消息或者修改主线程的UI的方法是,在子线程获取主线程里的Handler对象,通过这个对象向主线程的MessageQueue中发送消息,进行通信或者操作。

比如在子线程中更新主线程中的UI,可以在子线程中通过mhandler.post(Runnable r)将runnable加入到主线程的MessageQueue中,然后主线程将调用runnable的方法,可以在此方法中更新主线程UI。

同样也可以使用mhandler.sendMessage(Message msg)向主线程中发送消息。

猜你喜欢

转载自blog.csdn.net/zjpp2580369/article/details/83183484