Android多线程
在了解Handler类之前,我们有必要熟悉以下Java的多线程编程
线程的基本用法
class MyThread extends Thread{
public void run(){
}
}
new MyThread().start();
更多的时候我们都会选择使用Runnable接口的方式来定义一个线程,如下
class MyThread implements Runnable{
public void run(){
}
}
MyThread myThread = new MyThread();
new Thread(myThread).start();
Handler类简介
Handler是Android提供的一个用来更新UI的机制(Android不允许在子线程更新UI),也是一个消息处理的机制。通过Handler类可以发送和处理Message对象到其所在线程的MessageQueue中。Handler类主要有以下两个作用、
1、在任意线程中发送消息
将Message应用sendMessage()方法发送到MessageQueue中,在发送时可以指定延时时间、发送时间以及携带的Bundle数据。当Looper循环到该Message时,调用相应的Handler对象handlerMessage()方法进行处理
2、在主线程中获取并处理消息
为了让主线程能在适当的时候处理Handler所发送的消息,必须通过回调方法来实现。
Handler类包含了一些用于发送和处理消息的常用方法
消息类(Message)
消息类是存放在MessageQueue中,一个MessageQueue中可以包含许多Message对象,每个Message对象可以通过Message.obtain()或Handler.obtainMessage()方法获得,属性如下:
- arg1 用来存放整型数据
- arg2 用来存放整型数据
- obj 用来存放发送给接收器的Object类型的任意对象
- replyTo 用来指定此Message发送到何处的可选Messager对象
- what 用来指定用户自定义消息代码,能够用不同方式处理Message
循环者(Looper)
系统会为主线程创建Looper对象,开启消息循环,而子线程默认情况不会开启消息循环。
如果在子线程创建Handler对象,首先需要使用Looper类的 prepare() 方法初始化一个Looper对象,然后创建该Handler对象,最后使用Looper类的loop()方法启动Looper,从消息队列获取和处理消息.
从以上可以看出,Android的异步消息由4个部分组成:Message、Handler、MessageQueue和Looper。
- Message是在线程之间传递的消息、可以在内部携带少量的消息,用于在不同线程之间交换数据。
- Handler主要用于发送和处理消息。发送消息一般是使用Handler的sendMessage(),发出消息经过一系列处理,最终会传递到Handler的handleMessage()方法中。
- MessageQueue消息队列,存放所有通过Handler发送的消息,每个线程只能由一个MessageQueue对象
- Looper是管理MessageQueue的,调用Looper loop()方法后,进入一个无限循环,每当发现MessageQueue中存在一条消息,便会取出,传递到handleMessage()。每个线程中也只会有一个Looper对象
handler发送消息到MessageQueue中,然后Looper会尝试从MessageQueue取出消息,最后分发回Handler的handleMessage()方法中,由于Handler是在主线程中创建,所以此时handleMessage()方法代码会在主线程中运行,也就能安心进行UI操作。
实例:图片轮播
slide_in_right.xml
<translate
android:duration="500"
android:fromXDelta="100%p"
android:toXDelta="0"/>
slide_out_left.xml
<translate
android:duration="500"
android:fromXDelta="0"
android:toXDelta="-100%p"/>
activity_main.xml
<ViewFlipper
android:id="@+id/viewFlipper"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
</ViewFlipper>
MainActivity
public class MainActivity extends AppCompatActivity {
final int FLAG_MSG = 0x001; //定义发送的消息代码
private ViewFlipper flipper;
private Message message; //声明消息对象
private int[] images = new int[]{ //图片
R.drawable.img1,R.drawable.img2,
R.drawable.img3,
R.drawable.img4,
R.drawable.img5,
R.drawable.img6,
R.drawable.img7,
R.drawable.img8,
};
private Animation[] animation = new Animation[2]; //定义动画数组
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
flipper = (ViewFlipper) findViewById(R.id.viewFlipper);
for(int i=0;i<images.length;i++){
ImageView imageView = new ImageView(this);
imageView.setImageResource(images[i]);
flipper.addView(imageView);
}
//初始化动画数组
animation[0] = AnimationUtils.loadAnimation(this,R.anim.slide_in_right); //设置简单的淡入淡出动画
animation[1] = AnimationUtils.loadAnimation(this,R.anim.slide_out_left);
flipper.setInAnimation(animation[0]);
flipper.setOutAnimation(animation[1]);
message = Message.obtain();
message.what = FLAG_MSG;
handler.sendMessage(message);
}
Handler handler = new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
if (msg.what==FLAG_MSG){ //接收到的是消息标记,能用于处理不同类型的消息.
flipper.showPrevious();
}
message = handler.obtainMessage(FLAG_MSG); //获取要发送的消息.
handler.sendMessageDelayed(message,3000); //延迟3秒发送消息.
}
};
}
运行效果如下,延迟3s切换图片
小结:
Thread和Handler的区别
创建一个Thread就是在程序中创建了一个子线程,用于在Android中不能在子线程(Worker线程)中更新主线程(UI线程)内的UI组件,因此Android引入消息传递机制,通过Looper、Handler和Message轻松实现在多线程中更新UI界面的功能。