在Android系统中,多线程之间传递消息我们可以用Handler来实现
UI线程向子线程发送消息,子线程接收到消息后处理
public class MainToWorkThreadActivity extends Activity {
private Handler handler;
private Button button1;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main_to_work_thread);
button1 = (Button) findViewById(R.id.button1);
button1.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// 在主线程发送消息
System.out.println("onClick: "
+ Thread.currentThread().getName());
Message msg = handler.obtainMessage();
msg.what = 100;
handler.sendMessage(msg);
}
});
new Thread() {
@Override
// 在线程中处理主线程发送的消息对象
// 为什么工作线程中需要Looper对象,而主线程不需要??
public void run() {
// 准备Looper对象
Looper.prepare();
// 在WorkThread当中生成一个Handler对象
handler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
System.out.println("handleMessage: " + Thread.currentThread().getName());
}
};
// 调用Looper的loop()方法之后,Looper对象将不断的从消息队列中取出消息对象,
// 然后调用handlerMessage()方法处理该消息对象
// 如果消息队列中没有对象,则该线程阻塞
Looper.loop();
}
}.start();
}
}
子线程向UI线程发送消息,UI线程接收消息后处理
public class WorkToMainThreadActivity extends Activity {
private Button button1, button2, button3;
private ProgressBar progressBar;
private Handler handler;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_maintoworkthread);
button1 = (Button) findViewById(R.id.button1);
button2 = (Button) findViewById(R.id.button2);
button3 = (Button) findViewById(R.id.button3);
progressBar = (ProgressBar) findViewById(R.id.progressBar);
progressBar.setMax(100);
/*
* 在java中可有两种方式实现多线程,一种是继承Thread类,一种是实现Runnable接口;
* Thread类是在java.lang包中定义的。一个类只要继承了Thread类同时覆写了本类中的run()
* 方法就可以实现多线程操作了,但是一个类只能继承一个父类,这是此方法的局限。 两种实现方式的区别和联系:
*
* 在程序开发中只要是多线程肯定永远以实现Runnable接口为主,因为实现Runnable接口相比继承Thread类有如下好处:
* 1.避免点继承的局限,一个类可以继承多个接口。 2.适合于资源的共享
*/
button1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// 继承Thread方法实现多线程
new Thread() {
@Override
public void run() {
System.out.println("button1.onClick.run: " + Thread.currentThread().getId()+ Thread.currentThread().getName());
try {
int i = 5;
while (i <= 100) {
sleep(500);
Message msg = handler.obtainMessage();
msg.arg1 = i;
handler.sendMessage(msg);
// 上面一行代码将消息对象放置到消息队列当中
// 1.Looper将会从消息队列当中将消息对象取出
// 2.Looper将会找到与消息对象对应的Handler对象
// 3.Looper将会调用handler对象的handleMessage(Message msg)方法,用于处理消息对象
i += 5;
}
} catch (InterruptedException e) {
e.printStackTrace();
}
super.run();
}
}.start();
}
});
button2.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
/*
* 在实际开发中一个多线程的操作很少使用Thread类,而是通过Runnable接口完成。
* 但是在使用Runnable定义的子类中没有start()方法,只有Thread类中才有。
* 此时观察Thread类,有一个构造方法:public Thread(Runnable targer)此构造方法接受Runnable的子类实例,
* 也就是说可以通过Thread类来启动Runnable实现的多线程。(start()可以协调系统的资源)
*/
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("button2.onClick.run: " + Thread.currentThread().getId()+ Thread.currentThread().getName());
try {
int i = 10;
while (i <= 100) {
Thread.sleep(1000);
Message msg = handler.obtainMessage();
msg.arg1 = i;
handler.sendMessage(msg);
i += 10;
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
}
});
button3.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
/*
* Runnable对象和主用户界面线程的ID是相同。在这个例子中,我们直接利用handler对象post了一个runnable对象
* ,相当于直接调用了Runnable对象的run函数,也就说没有经过start函数调用run(),那么就不会创建一个新线程,
* 而是在原有线程内部直接调用 run()方法,因此输出的线程Id是相同的。
*/
handler.post(new Runnable() {
@Override
public void run() {
System.out.println("button3.onClick.run: " + Thread.currentThread().getId()+ Thread.currentThread().getName());
try {
int i = 1;
while (i <= 100) {
Thread.sleep(100);
Message msg = handler.obtainMessage();
msg.arg1 = i;
handler.sendMessage(msg);
i += 1;
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
}
});
handler = new Handler() {
@Override
public void handleMessage(Message msg) {
// 在主线程处理消息,工作线程发送消息,以方便线程间通信
// 这样可以解决工作线程不能操作UI的问题
System.out.println("handleMessage: " + Thread.currentThread().getId() + Thread.currentThread().getName());
progressBar.setProgress(msg.arg1);
super.handleMessage(msg);
}
};
}
}