处于性能优化考虑,Android的UI操作并不是线程安全的,这意味着如果有多个线程并发操作UI组件,则可能导致线程安全问题。为了解决这个问题,Android制定了一条简单的规则:只允许UI线程修改Activity中的UI组件。
当程序一个程序第一次启动时,Android会同时启动一条主线程(Main Thread),主线程主要负责处理与UI相关的事件,如用户的按键事件,用户接触屏幕的事件以及屏幕绘图事件,并把相关事件分发到对应的组件进行处理。所以,主线程通常又被叫做UI线程。
Android的消息传递机制时另一种形式的“事件处理”,这种机制主要是为了解决Android应用的多线程问题——Android平台只允许UI线程修改Activity中的UI组件,这样就会导致新启动的线程无法动态改变界面组件的属性值。但实际Android应用开发中,尤其时涉及到动画的游戏开发中,需要让新启动的线程周期性的改变界面组件的属性值,贼就需要借助于Handler的消息传递机制啦i实现了。
>>3.5.1 Handler类简介
Handler类的主要作用由两个。
> 在新启动的线程中发送消息
> 在主线程中获取,处理消息。
上面的说法看上去简单,似乎只要分成两部即可:在新启动的线程中发送消息;然后再主线程中获取并处理消息。但这个问题涉及到两个问题:新启动的线程何时发送消息呢?主线程何时获取并处理消息?这个时机显然不好控制。
为了让主线程“适时”地处理新启动的线程所发送的消息,显然只能通过回调的方式来实现——开发者只需要重写Handler类中处理消息的方法,当新启动的线程发送消息时,消息会发送到与之关联的MessageQuanue,而Handler会不断地从MessageQueue中获取并处理消息——这将1导致Handler类中处理消息的方法被huidiao。
Handler中包含如下方法用于发送,处理消息。
>void handlerMessage(Message msg):处理消息的方法。该方法通常用于被重写。
>final boolean hasMessages(int what):检查消息队列中是否包含what属性为指定值的消息.
>final boolean hasMessage(int what,Object object) :检查消息队列中是否包含what属性为指定值且object属性为指定对象的消息.
>多个重载的Message obtainMessage():获取消息.
>sendEmptyMessage(int what) :发送空消息.
>fianl boolean sendEmptyMessageDelayed(int what,long delayMillis):指定多少毫秒后发送空消息.
>final Boolean sendMessage(Message msg): 立即发送消息.
>fianl boolean sendMessageDelayed(Message msg,long delayMillis) :指定多少毫秒后发送消息.
实例:自动播放动画
public class MainActivity extends AppCompatActivity {
private ImageView imageView;
int []images={R.drawable.h_1,R.drawable.h_2,R.drawable.h_3};
int curentImage=1;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
imageView= (ImageView) findViewById(R.id.show_pic);
final Handler handler=new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
imageView.setImageResource(images[++curentImage % images.length]);
}
};
//设一个定时器,每隔一秒发送一次消息
Timer timer=new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
handler.sendEmptyMessage(0x123);
}
},0,1000);
}
}