原文地址: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所显示的图片。实现一个动画效果。
-
public?class?HandlerActivity?extends?Activity?{??
-
??????????
-
????????int[]?imageIds?=?new?int[]??
-
????????{??
-
????????????????R.drawable.1,??
-
????????????????R.drawable.2,??
-
????????????????R.drawable.3,??
-
????????????????R.drawable.4,??
-
????????????????R.drawable.5??
-
????????};??
-
????????int?currentImageId?=?0;??
-
????????@Override??
-
????????public?void?onCreate(Bundle?savedInstanceState)??
-
????????{??
-
????????????super.onCreate(savedInstanceState);??
-
????????????setContentView(R.layout.main_activity);??
-
????????????final?ImageView?show?=?(ImageView)?findViewById(R.id.main_bt);??
-
??????????????
-
????????????final?Handler?myhHandler?=?new?Handler()??
-
????????????{??
-
????????????????@Override??
-
????????????????public?void?handleMessage(Message?msg)??
-
????????????????{??
-
??????????????????????
-
????????????????????if?(msg.what?==?0x12345)?{??
-
??????????????????????????
-
????????????????????????show.setImageResource(imageIds[currentImageId++]%imageIds.length);??
-
????????????????????}??
-
????????????????}??
-
????????????};??
-
??????????????
-
????????????new?Timer().schedule(new?TimerTask()?{???
-
??????????????????
-
????????????????@Override??
-
????????????????public?void?run()?{??
-
??????????????????????
-
??????????????????????
-
????????????????????myhHandler.sendEmptyMessage(0x12345);??
-
????????????????}??
-
????????????},?0,?1200);??
-
????????}??
-
????}??
说明:当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()方法),以下解说这两个方法:
-
public?static?final?void?prepare(){??
-
????????if?(sThreadLocal.get()?!=?null)?{??
-
????????????throw?new?RuntimeException("Only?one?Looper?may?be?created?per?thread");??
-
????????}??
-
????????sThreadLocal.set(new?Looper());??
-
????}??
说明:prepare方法保证线程最多仅仅有一个Looper对象。
-
public?void?loop(){??
-
????????for?(;?;)?{??
-
????????????Message?msg?=?queue.next();??
-
????????????if?(msg?==?null)?{??
-
????????????????return;??
-
????????????}??
-
????????????Printer?logging?=?me.mLogging;??
-
????????????if?(logging?!=?null)?{??
-
????????????????logging.println("");??
-
????????????}??
-
????????????msg.target.dispatchMessage(msg);??
-
????????????if?(logging?!=?null)?{??
-
????????????????logging.println("");??
-
????????????}??
-
??????????????
-
????????????final?long?newIdent?=?Binder.clearCallingIdentity();??
-
????????????if?(iden?!=?newIdent)?{??
-
????????????????logging.println("");??
-
????????????}??
-
????????????msg.recycle();??
-
????????}??
-
????}??
说明:loop()方法使用一个死循环不断取出MessageQueue中的消息,并将取出的消息分给该消息相应的Handler进行处理。
在非主线程中使用Handler的过程例如以下:
- 调用Looper的prepare()方法为当前线程创建Looper对象(创建Looper对象时。它的构造器会自己主动创建与之配套的MessageQueue)。
- 有了Looper之后,创建Handler子类的实例,重写handleMessage()方法。该方法负责处理来自于其它线程的消息。
- 调用Looper的loop()方法启动Looper。
Demo:使用新线程计算质数
该实例同意用户输入一个数值上限,当用户单击“计算”button时,该应用会将该上限数值发送到新启动的线程。让该线程来计算该范围内的全部质数(之所以不直接在UI线程中计算该范围的全部质数。是由于UI线程须要响应用户动作,假设在UI线程中运行一个耗时操作,将会导致UI线程被堵塞。引起ANR异常)。
-
?
-
?
-
???
-
????public?class?CalPrime?extends?Activity{??
-
????????static?final?String?UPPER_NUM?=?"upper";??
-
????????EditText?etNum;??
-
????????CalThread?calThread;??
-
????????class?CalThread?extends?Thread{??
-
????????????public?Handler?mHandler;??
-
????????????public?void?run(){??
-
????????????????Looper.prepare();??
-
????????????????mHandler?=?new?Handler(){??
-
????????????????????@Override??
-
????????????????????public?void?handleMessage(Message?msg){??
-
????????????????????????if?(msg.what?==?0x123)?{??
-
????????????????????????????int?upper?=?msg.getData().getInt(UPPER_NUM);??
-
????????????????????????????List<Integer>?nums?=?new?ArrayList<Integer>();??
-
??????????????????????????????
-
????????????????????????????outer:??
-
????????????????????????????????for?(int?i?=?2;?i?<=?upper;?i++)?{??
-
??????????????????????????????????????
-
????????????????????????????????????for?(int?j?=?2;?j?<=?Math.sqrt(i);?j++)?{??
-
??????????????????????????????????????????
-
????????????????????????????????????????if?(i?!=?2?&&?i?%?j?==?0)?{??
-
????????????????????????????????????????????continue?outer;??
-
????????????????????????????????????????}??
-
????????????????????????????????????}??
-
????????????????????????????????????nums.add(i);??
-
????????????????????????????????}??
-
??????????????????????????????
-
????????????????????????????Toast.makeText(CalPrime.this,?nums.toString(),?Toast.LENGTH_LONG).show();??
-
??????????????????????????????
-
????????????????????????}??
-
????????????????????}??
-
????????????????};??
-
????????????????Looper.loop();??
-
????????????}??
-
????????}??
-
????}??
-
????@Override??
-
????public?void?onCreate(Bundle?savedInstanceState){??
-
????????super.onCreate(savedInstanceState);??
-
????????setContentView(R.layout.main_activity);??
-
????????etNum?=?(EditText)findViewById(R.id.etNum);??
-
????????CalThread?calThread?=?new?CalThread();??
-
????????calThread.start();??
-
????}??
-
??????
-
????public?void?cal(View?source){??
-
??????????
-
????????Message?msg?=?new?Message();??
-
????????msg.what?=?0x123;??
-
????????Bundle?bundle?=?new?Bundle();??
-
????????bundle.putInt(UPPER_NUM,?Integer.parseInt(etNum.getText().toString()));??
-
????????msg.setData(bundle);??
-
??????????
-
????????calThread.mHandler.sendMessage(msg);??
-
??????????
-
????}??