Handler类和Handler,Loop,MessageQueue的工作原理

Posted llguanli

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Handler类和Handler,Loop,MessageQueue的工作原理相关的知识,希望对你有一定的参考价值。

原文地址:http://blog.csdn.net/xiyangyang8/article/details/50754771


Handler类的作用主要有两种:

1.在新启动的线程中发送消息。

2.在主线程(UI线程)中获取,处理消息。

注:主线程已经封装有Loop的消息队列处理机制,无需再创建。

Handler类包括例如以下方法用于消息发送,处理:

1.void handleMessage(Message msg):处理消息的方法。

2.final boolean hasMessages(int what):检查消息队列是否包括what的值。

3.final boolean hasMessages(int what, Object object):检查消息队列是否包括what的值且object为指定对象。

4.Message obtainMessage():获取消息。

5.sendEmptyMessage(int what):发送空消息。

6.final boolean sendemptyMessageDelayed(int what, long delayMillis):指定多少毫秒之后发送空消息。

7.final boolean sendMessage(Message msg):马上发送消息。

8.final boolean sendMessageDelayed(Message msg, long delayMillis):指定多少毫秒之后发送空消息。

?

demo:自己主动播放动画

以下代码实现是创建一个新线程来隔一定时间之后周期性的改动ImageView所显示的图片。实现一个动画效果。

[java]?view plain?copy
?技术分享图片技术分享图片
  1. public?class?HandlerActivity?extends?Activity?{??
  2. ????????//定义周期性显示的图片ID??
  3. ????????int[]?imageIds?=?new?int[]??
  4. ????????{??
  5. ????????????????R.drawable.1,??
  6. ????????????????R.drawable.2,??
  7. ????????????????R.drawable.3,??
  8. ????????????????R.drawable.4,??
  9. ????????????????R.drawable.5??
  10. ????????};??
  11. ????????int?currentImageId?=?0;??
  12. ????????@Override??
  13. ????????public?void?onCreate(Bundle?savedInstanceState)??
  14. ????????{??
  15. ????????????super.onCreate(savedInstanceState);??
  16. ????????????setContentView(R.layout.main_activity);??
  17. ????????????final?ImageView?show?=?(ImageView)?findViewById(R.id.main_bt);??
  18. ??????????????
  19. ????????????final?Handler?myhHandler?=?new?Handler()??
  20. ????????????{??
  21. ????????????????@Override??
  22. ????????????????public?void?handleMessage(Message?msg)??
  23. ????????????????{??
  24. ????????????????????//假设该消息是本程序所发送的??
  25. ????????????????????if?(msg.what?==?0x12345)?{??
  26. ????????????????????????//动态的改动所显示的图片??
  27. ????????????????????????show.setImageResource(imageIds[currentImageId++]%imageIds.length);??
  28. ????????????????????}??
  29. ????????????????}??
  30. ????????????};??
  31. ????????????//定义一个计时器,让该计时器周期性的运行指定任务??
  32. ????????????new?Timer().schedule(new?TimerTask()?{?//TimerTask对象的本质是启动一个新线程??
  33. ??????????????????
  34. ????????????????@Override??
  35. ????????????????public?void?run()?{??
  36. ????????????????????//?TODO?Auto-generated?method?stub??
  37. ????????????????????//发送空消息??
  38. ????????????????????myhHandler.sendEmptyMessage(0x12345);??
  39. ????????????????}??
  40. ????????????},?0,?1200);??
  41. ????????}??
  42. ????}??

说明:当Timertask新线程发送消息时。位于主线程的handleMessage(Message msg)方法自己主动被回调。动态的改动ImagView组件的属性。效果:由新线程来周期性的改动ImageView的属性。从而实现动画效果。

?

Handler,Looper。MessageQueue的工作原理:

Looper:每一个线程仅仅有一个Looper,它负责管理MessageQueue,会不断的从MessageQueue中取出消息,并将消息分发给Handler处理。

MessageQueue:由Looper负责管理。

它採用先进先出的方式来管理Message。

Handler:它能把消息发送给Looper管理的MessageQueue。并负责处理Looper分给它的消息。

注:

  • 在主线程中。系统已经初始化了一个Looper对象,因此程序直接创建Handler就可以,然后就可通过Handler来发送消息,处理消息。
  • 在自己启动的子线程。必须自己创建一个Looper对象,并启动它(分别调用prepare()和loop()方法),以下解说这两个方法:
[java]?view plain?copy
?技术分享图片技术分享图片
  1. public?static?final?void?prepare(){??
  2. ????????if?(sThreadLocal.get()?!=?null)?{??
  3. ????????????throw?new?RuntimeException("Only?one?Looper?may?be?created?per?thread");??
  4. ????????}??
  5. ????????sThreadLocal.set(new?Looper());??
  6. ????}??

说明:prepare方法保证线程最多仅仅有一个Looper对象。

[java]?view plain?copy
?技术分享图片技术分享图片
  1. public?void?loop(){??
  2. ????????for?(;?;)?{??
  3. ????????????Message?msg?=?queue.next();//获取消息队列的下一个消息。假设没有消息,将会堵塞??
  4. ????????????if?(msg?==?null)?{//假设消息为null,表明消息队列正在退出??
  5. ????????????????return;??
  6. ????????????}??
  7. ????????????Printer?logging?=?me.mLogging;??
  8. ????????????if?(logging?!=?null)?{??
  9. ????????????????logging.println("");??
  10. ????????????}??
  11. ????????????msg.target.dispatchMessage(msg);??
  12. ????????????if?(logging?!=?null)?{??
  13. ????????????????logging.println("");??
  14. ????????????}??
  15. ????????????//使用final修饰该标识符。保证在分发消息的过程中线程标识符不会被改动??
  16. ????????????final?long?newIdent?=?Binder.clearCallingIdentity();??
  17. ????????????if?(iden?!=?newIdent)?{??
  18. ????????????????logging.println("");??
  19. ????????????}??
  20. ????????????msg.recycle();??
  21. ????????}??
  22. ????}??

说明:loop()方法使用一个死循环不断取出MessageQueue中的消息,并将取出的消息分给该消息相应的Handler进行处理。


在非主线程中使用Handler的过程例如以下:

  • 调用Looper的prepare()方法为当前线程创建Looper对象(创建Looper对象时。它的构造器会自己主动创建与之配套的MessageQueue)。
  • 有了Looper之后,创建Handler子类的实例,重写handleMessage()方法。该方法负责处理来自于其它线程的消息。
  • 调用Looper的loop()方法启动Looper。

Demo:使用新线程计算质数

该实例同意用户输入一个数值上限,当用户单击“计算”button时,该应用会将该上限数值发送到新启动的线程。让该线程来计算该范围内的全部质数(之所以不直接在UI线程中计算该范围的全部质数。是由于UI线程须要响应用户动作,假设在UI线程中运行一个耗时操作,将会导致UI线程被堵塞。引起ANR异常)。

[java]?view plain?copy
?技术分享图片技术分享图片
  1. /*?
  2. ?????*?本实例在线程中创建一个Handler对象,然后UI线程的事件处理方法通过Handler向新线程发送消息。?
  3. ?????*/???
  4. ????public?class?CalPrime?extends?Activity{??
  5. ????????static?final?String?UPPER_NUM?=?"upper";??
  6. ????????EditText?etNum;??
  7. ????????CalThread?calThread;??
  8. ????????class?CalThread?extends?Thread{??
  9. ????????????public?Handler?mHandler;??
  10. ????????????public?void?run(){??
  11. ????????????????Looper.prepare();??
  12. ????????????????mHandler?=?new?Handler(){??
  13. ????????????????????@Override??
  14. ????????????????????public?void?handleMessage(Message?msg){??
  15. ????????????????????????if?(msg.what?==?0x123)?{??
  16. ????????????????????????????int?upper?=?msg.getData().getInt(UPPER_NUM);??
  17. ????????????????????????????List<Integer>?nums?=?new?ArrayList<Integer>();??
  18. ????????????????????????????//计算从2開始,到upper的全部质数??
  19. ????????????????????????????outer:??
  20. ????????????????????????????????for?(int?i?=?2;?i?<=?upper;?i++)?{??
  21. ????????????????????????????????????//用i除以从2開始。到i的平方根的全部数??
  22. ????????????????????????????????????for?(int?j?=?2;?j?<=?Math.sqrt(i);?j++)?{??
  23. ????????????????????????????????????????//假设能够整除。表明这个数不是质数??
  24. ????????????????????????????????????????if?(i?!=?2?&&?i?%?j?==?0)?{??
  25. ????????????????????????????????????????????continue?outer;??
  26. ????????????????????????????????????????}??
  27. ????????????????????????????????????}??
  28. ????????????????????????????????????nums.add(i);??
  29. ????????????????????????????????}??
  30. ????????????????????????????//使用Toast显示统计出来的全部质数??
  31. ????????????????????????????Toast.makeText(CalPrime.this,?nums.toString(),?Toast.LENGTH_LONG).show();??
  32. ??????????????????????????????
  33. ????????????????????????}??
  34. ????????????????????}??
  35. ????????????????};??
  36. ????????????????Looper.loop();??
  37. ????????????}??
  38. ????????}??
  39. ????}??
  40. ????@Override??
  41. ????public?void?onCreate(Bundle?savedInstanceState){??
  42. ????????super.onCreate(savedInstanceState);??
  43. ????????setContentView(R.layout.main_activity);??
  44. ????????etNum?=?(EditText)findViewById(R.id.etNum);??
  45. ????????CalThread?calThread?=?new?CalThread();??
  46. ????????calThread.start();//启动新线程??
  47. ????}??
  48. ????//为button的点击事件提供事件处理函数??
  49. ????public?void?cal(View?source){??
  50. ????????//创建消息??
  51. ????????Message?msg?=?new?Message();??
  52. ????????msg.what?=?0x123;??
  53. ????????Bundle?bundle?=?new?Bundle();??
  54. ????????bundle.putInt(UPPER_NUM,?Integer.parseInt(etNum.getText().toString()));??
  55. ????????msg.setData(bundle);??
  56. ????????//向新线程中的Handler发送消息??
  57. ????????calThread.mHandler.sendMessage(msg);??
  58. ??????????
  59. ????}??

以上是关于Handler类和Handler,Loop,MessageQueue的工作原理的主要内容,如果未能解决你的问题,请参考以下文章

Handler类和Handler,Loop,MessageQueue的工作原理

Binder 机制Native 层 Binder 机制分析 ( binder_loop | svcmgr_handler | binder.c | binder_parse )

Android Handler那些事儿,消息屏障?IdelHandler?ANR?

Looper和Handler的分析

Handler机制中的五大对象

我所知道的Handler