[置顶] 温故知新.Handler消息传递机制.
2017-08-03 23:28
211 查看
忙里抽闲,赶紧打开电脑温故下学过用过而又快被时间冲掉的知识点…..。
说上去看似很简单,似乎只要分成两步即可:
但这个过程涉及两个问题:
这个时机显然不好控制,为了让主线程能”适时”地处理新启动的线程所发送的消息,显然只能通过回调的方式来实现–使用的时候只要重写Handler类中处理消息的方法,当新启动的线程发送消息时,消息会发送到与之关联的MessageQueue,而Handler会不断地从MessageQueue中获取并处理消息,这就会导致Handler类中处理消息的方法被回调。
Handler类包含如下方法用于发送、处理消息。<看过源码的人都知道>
有了以上这些方法,程序可以方便地利用Handler来进行消息传递。
以上代码重写了Handler的handleMessage(Message msg)方法,该方法用于处理消息——当新线程发送消息时,该方法会被自动回调,handlerMessage(Message msg)方法依然位于主线程中,所以可以动态地修改ImageView组件的属性。
这就实现了小实例所要达到的效果:
直奔主题
出于性能优化考虑,Android系统的UI的操作并不是线程安全的,这意味着如果有多个线程并发操作UI组件,则可能导致线程安全带问题。为了解决这个问题,Android制定了一条简单的规则:只允许UI线程修改Activity里的UI组件。 当一个程序第一次启动时,Android会同时启动一条主线程(Main Thread),主线程主要负责处理与UI相关的事件,如用户的按键事件、用户接触屏幕的事件及屏幕绘图事件,并把相关的事件分发到对应的组件进行处理。So,主线程通常又被叫作UI线程。 Android的消息传递机制是另一种形式的"事件处理",这种机制主要是为了解决Android应用的多线程问题 Android平台只允许UI线程修改Activity里的UI组件,这样就会导致新启动的线程无法动态 改变界面组件的属性值。但在实际Android应用开发中,尤其是涉及动画的游戏开发中,需要让新启动的线程 周期性地改变界面组件的属性值,这就需要借助于Handler的消息传递机制来实现。
Handler类的主要作用有两个
1. 在新启动的线程中发送消息。 2. 在主线程中获取、处理消息。
说上去看似很简单,似乎只要分成两步即可:
在新启动的线程中发送消息;然后在主线程中获取并处理消息。
但这个过程涉及两个问题:
1.新启动的线程何时发送消息呢? 2.主线程何时去获取并处理消息呢?
这个时机显然不好控制,为了让主线程能”适时”地处理新启动的线程所发送的消息,显然只能通过回调的方式来实现–使用的时候只要重写Handler类中处理消息的方法,当新启动的线程发送消息时,消息会发送到与之关联的MessageQueue,而Handler会不断地从MessageQueue中获取并处理消息,这就会导致Handler类中处理消息的方法被回调。
Handler类包含如下方法用于发送、处理消息。<看过源码的人都知道>
//处理消息的方法,该方法通常用于被重写 @Override public void handleMessage(Message msg) { super.handleMessage(msg); } //检查消息队列中是否包含what属性为指定值得消息 public final boolean hasMessages(int what) { return mQueue.hasMessages(this, what, null); } //检查消息队列中是否包含what属性为指定值且object属性为指定对象的消息 public final boolean hasMessages(int what, Object object) { return mQueue.hasMessages(this, what, object); } //多个重载obtainMessage 获取消息。 public final Message obtainMessage() { return Message.obtain(this); } public final Message obtainMessage(int what) { return Message.obtain(this, what); } public final Message obtainMessage(int what, Object obj) { return Message.obtain(this, what, obj); } public final Message obtainMessage(int what, int arg1, int arg2) { return Message.obtain(this, what, arg1, arg2); } public final Message obtainMessage(int what, int arg1, int arg2, Object obj) { return Message.obtain(this, what, arg1, arg2, obj); } //发送空消息 public final boolean sendEmptyMessage(int what) { return sendEmptyMessageDelayed(what, 0); } //指定多少毫秒之后发送空消息 public final boolean sendEmptyMessageDelayed(int what, long delayMillis) { Message msg = Message.obtain(); msg.what = what; return sendMessageDelayed(msg, delayMillis); } //立即发送消息 public final boolean sendMessage(Message msg) { return sendMessageDelayed(msg, 0); } //指定多少毫秒之后发送消息 public final boolean sendMessageDelayed(Message msg, long delayMillis) { if (delayMillis < 0) { delayMillis = 0; } return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis); }
有了以上这些方法,程序可以方便地利用Handler来进行消息传递。
说了那么多没卵用的! 没人给勇气都看不下去了..... 客官~ 骚等.... 小二马上附上一份极间的代码案例!
自动播放动画实例:
实例通过一个新线程来周期性地修改ImageView所显示的图片,通过这种方式来开发一个动画效果, 为了演示写的非常简单,程序只是在界面布局中定义了ImageView组件,就不贴XML布局代码了。
//主程序使用java.util包下的Timer来周期性的执行指定任务: public class mainsActivity extends Activity { //定义周期性显示的图片 ID int[] imageIds =new int[]{ R.drawable.one, R.drawable.two, R.drawable.three, R.drawable.four, R.drawable.five }; int currentImageId =0; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); final ImageView show=(ImageView) findViewById(R.id.show); final Handler mHandler = new Handler(){ @Override public void handleMessage(Message msg) { //如果该消息是本程序所发送的 if (msg.what == 0x1233){ //动态地修改所显示的图片 show.setImageResource(imageIds[currentImageId++ % imageIds.length]); } } }; //定义一个计时器,让该计时器周性地执行任务 new Timer().schedule(new TimerTask(){ @Override public void run() { //发送消息 mHandler.sendEmptyMessage(0x1233); } },0,1500); } }
小实例细说
上实例中通过Timer周期性地执行指定任务,Timer对象可调度TimerTask对象,TimerTask对象的本质就是启动一条线程,原因Android不允许在新线程中访问Activity里的界面组件,因此只能在新线程里发送一条消息,通知系统更新ImageView组件。以上代码重写了Handler的handleMessage(Message msg)方法,该方法用于处理消息——当新线程发送消息时,该方法会被自动回调,handlerMessage(Message msg)方法依然位于主线程中,所以可以动态地修改ImageView组件的属性。
这就实现了小实例所要达到的效果:
由新线程来周期性的修改ImageView属性,从而实现动画效果,运行上面的小实例,达到5张图片交替显示的动态效果。
明天待续Handler 、Loop、MessageQueue
他们之间是怎么成为老铁的………
相关文章推荐
- Android 源码解析Handler消息传递机制
- Handler消息传递机制(一)
- Android中Handler消息传递机制
- Handler消息传递机制
- 【Android基础笔记19】Handler、Looper消息传递机制
- Android消息传递机制----Handler
- android-消息传递机制Message、MessageQueue、Handler、Looper
- Handler消息传递机制
- Handler消息传递机制
- [置顶] 面试时最常问到的Handler消息机制源码详解
- 3.5 Handler消息传递机制
- Handler消息传递机制
- 学习Android Handler消息传递机制
- Android 中 Handler 消息传递机制
- Handler消息传递机制——Handler类简洁
- Handler消息传递机制之Looper
- Handler消息传递机制
- Handler 消息传递机制
- Handler消息传递机制(二) 教你认清Handler,Looper,MessageQueue
- Android 事件处理模型(三)消息传递机制: Handler Looper MessageQueue