当前位置:   article > 正文

android之Handler的使用,回到主线程更新UI的四种方法_handlerthread 通知ui主线程更新runonuithread

handlerthread 通知ui主线程更新runonuithread

Android为了线程安全,并不允许我们在UI线程外操作UI;很多时候我们做界面刷新都需要通过Handler来通知UI组件更新!除了用Handler完成界面更新外,还可以使用runOnUiThread()来更新,甚至更高级的事务总线。 

当我们的子线程想修改Activity中的UI组件时,我们可以新建一个Handler对象,通过这个对象向主线程发送信息;而我们发送的信息会先到主线程的MessageQueue进行等待,由Looper按先入先出顺序取出,再根据message对象的what属性分发给对应的Handler进行处理。

Handler运行在主线程中(UI线程中), 它与子线程可以通过Message对象来传递数据, 这个时候,Handler就承担着接受子线程传过来的(子线程用sedMessage()方法传弟)Message对象,(里面包含数据) , 把这些消息放入主线程队列中,配合主线程进行更新UI。

  • UI线程:就是我们的主线程,系统在创建UI线程的时候会初始化一个Looper对象,同时也会创建一个与其关联的MessageQueue;
  • Handler:作用就是发送与处理信息,如果希望Handler正常工作,在当前线程中要有一个Looper对象
  • Message:Handler接收与处理的消息对象
  • MessageQueue:消息队列,先进先出管理Message,在初始化Looper对象时会创建一个与之关联的MessageQueue;
  • Looper:每个线程只能够有一个Looper,管理MessageQueue,不断地从中取出Message分发给对应的Handler处理!

Handler在子线程中:

如果是Handler写在了子线程中的话,我们就需要自己创建一个Looper对象了!创建的流程如下:

1 )直接调用Looper.prepare()方法即可为当前线程创建Looper对象,而它的构造器会创建配套的MessageQueue; 

2 )创建Handler对象,重写handleMessage( )方法就可以处理来自于其他线程的信息了! 3 )调用Looper.loop()方法启动Looper

  1. new Thread(new Runnable() {
  2. @Override
  3. public void run() {
  4. /*
  5. * handler使用步骤
  6. *gei threadLocal设置了一个looper对象
  7. * 在looper的构造方法中,创建了一个messageQueue对象
  8. * */
  9. Looper.prepare();
  10. /*在构造方法中获取looper和looper中的messageQueue
  11. *
  12. * */
  13. Handler handler=new Handler(){
  14. @Override
  15. public void handleMessage(Message msg) {
  16. super.handleMessage(msg);
  17. }
  18. };
  19. /*奖message发送到messagequeue中,在messageQueue里面,所有的message都是时间为顺序从小到大排列
  20. *
  21. * */
  22. handler.sendEmptyMessage(0);
  23. /*
  24. *顺序取出messageQueue中的message
  25. *并且执行message。target。dispatchMessage();其中的message。target就是发送这个消息的handler
  26. * 每一条消息都有一定的执行时间,handler会判断时间有没有到,如果没到时间会等待,
  27. * */
  28. Looper.loop();
  29. }
  30. }).start();

 

----------handler的使用------

通过Message与Handler进行通信的步骤是: 
1. 重写Handler的handleMessage方法,根据Message的what值进行不同的处理操作 
2. 创建Message对象 
虽然Message的构造函数式public的,我们还可以通过Message.obtain()或Handler.obtainMessage()来获得一个Message对象(Handler.obtainMessage()内部其实调用了Message.obtain())。 
3. 设置Message的what值 
Message.what是我们自定义的一个Message的识别码,以便于在Handler的handleMessage方法中根据what识别出不同的Message,以便我们做出不同的处理操作。 
4. 设置Message的所携带的数据,简单数据可以通过两个int类型的field arg1和arg2来赋值,并可以在handleMessage中读取。 
5. 如果Message需要携带复杂的数据,那么可以设置Message的obj字段,obj是Object类型,可以赋予任意类型的数据。或者可以通过调用Message的setData方法赋值Bundle类型的数据,可以通过getData方法获取该Bundle数据。 
6. 我们通过Handler.sendMessage(Message)方法将Message传入Handler中让其在handleMessage中对其进行处理。 

需要说明的是,如果在handleMessage中 不需要判断Message类型,那么就无须设置Message的what值;而且让Message携带数据也不是必须的,只有在需要的时候才需要让其携带数据;如果确实需要让Message携带数据,应该尽量使用arg1或arg2或两者,能用arg1和arg2解决的话就不要用obj,因为用arg1和arg2更高效。

 

  1. Handler handler = new Handler()
  2. {
  3. public void handleMessage(android.os.Message msg) {
  4. switch (msg.what){
  5. case 1:
  6. String str= (String) msg.obj;
  7. reponsedattx.setText(str);
  8. break;
  9. }
  10. };
  11. };

 

 

 

  1. //get同步请求---http://ddb.cn/api/VlianbaoCash/deposit
  2. public void gettongbuDatasync(){
  3. new Thread(new Runnable() {
  4. @Override
  5. public void run() {
  6. OkHttpClient client = new OkHttpClient();//创建OkHttpClient对象
  7. Request request = new Request.Builder()
  8. .url(String.valueOf(test.getText()))//请求接口。如果需要传参拼接到接口后面。
  9. .build();//创建Request 对象
  10. Response response=null;
  11. try {
  12. response = client.newCall(request).execute();//得到Response 对象
  13. Log.e("kwwl","get同步res=="+response.body().string());
  14. String resstr=response.body().string();
  15. Message msg=new Message();
  16. //虽然Message的构造函数式public的,我们也可以通过以下两种方式通过循环对象获取Message
  17. //msg = Message.obtain(uiHandler);
  18. //msg = uiHandler.obtainMessage();
  19. //what是我们自定义的一个Message的识别码,以便于在Handler的handleMessage方法中根据what识别
  20. //出不同的Message,以便我们做出不同的处理操作
  21. msg.what = 1;
  22. //我们可以通过arg1和arg2给Message传入简单的数据
  23. msg.arg2 = 321;
  24. msg.obj="jjjj";
  25. //我们也可以通过给obj赋值Object类型传递向Message传入任意数据
  26. //msg.obj = null;
  27. //我们还可以通过setData方法和getData方法向Message中写入和读取Bundle类型的数据
  28. //msg.setData(null);
  29. //Bundle data = msg.getData();
  30. //将该Message发送给对应的Handler*****
  31. handler.sendMessage(msg);
  32. } catch (IOException e) {
  33. e.printStackTrace();
  34. }
  35. }
  36. }).start();
  37. }

 

 

 

-------回到主线程更新UI的四种方法,参考:https://blog.csdn.net/mislaydu/article/details/51776247

 

 

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/从前慢现在也慢/article/detail/133202
推荐阅读