使用Handler管理线程
步骤:
1. 申请一个Handler对象
Handler handler = new Handler();
2. 创建一个线程
{继承Thread类或者实现Runnable这个接口}
使用Runnable创建一个内部匿名类对象updateThread(要复写run方法)
3. 使用handler的post方法将线程加入到线程队列中
handler.post(updateThread);
4. 使用handler的removeCallbacks方法移出updateThread线程
注意:如果线程从线程队列中出来被执行后,则队列中就不在有线程
因此如果线程在被执行后没有方法将其再次加入到队列中,则无需使用removeCallbacks
线程走出线程队列有两种情况:
一种是被执行,此时要执行run方法
一种是使用removeCallbacks方法,此时线程不被执行,因此不调用run
5. 使用handler的postDelayed方法延时将线程加入到队列中
handler.postDelayed(updateThread,3000)
下面给出一个简单的代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
|
package
my.handler;
import
android.app.Activity;
import
android.os.Bundle;
import
android.os.Handler;
import
android.view.View;
import
android.view.View.OnClickListener;
import
android.widget.Button;
public
class
HandleruseActivity
extends
Activity {
/** Called when the activity is first created. */
//声明两个控件变量
private
Button startButton =
null
;
private
Button endButton =
null
;
@Override
public
void
onCreate(Bundle savedInstanceState) {
super
.onCreate(savedInstanceState);
setContentView(R.layout.main);
//获取控件对象
startButton = (Button)findViewById(R.id.startButton);
endButton = (Button)findViewById(R.id.endButton);
// 设置监听器
startButton.setOnClickListener(
new
startListener());
endButton.setOnClickListener(
new
endListener());
}
class
startListener
implements
OnClickListener{
@Override
public
void
onClick(View v) {
// TODO Auto-generated method stub
// 将线程updateThread加入到线程队列中
handler.post(updateThread);
}
}
class
endListener
implements
OnClickListener{
@Override
public
void
onClick(View v) {
// TODO Auto-generated method stub
// 将线程updateThread移出线程队列
handler.removeCallbacks(updateThread);
}
}
// 申请handler对象
Handler handler =
new
Handler();
// 创建一个线程,线程被调用时一定是调用其run函数
/* Runnable updateThread = new Runnable(){
public void run(){
System.out.println("UpdateThread");
// 延迟三秒之后将线程updateData加入到线程队列当中
handler.postDelayed(updateThread, 3000);
}
};*/
// 继承Runnable 或者继承 Thread
Thread updateThread =
new
Thread(){
public
void
run(){
System.out.println(
"UpdateThread Thread"
);
// 延迟三秒之后将线程updateData加入到线程队列当中
handler.postDelayed(updateThread,
3000
);
}
};
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
|
package
progressBar.handler;
import
android.app.Activity;
import
android.os.Bundle;
import
android.os.Handler;
import
android.os.Message;
import
android.view.View;
import
android.view.View.OnClickListener;
import
android.widget.Button;
import
android.widget.ProgressBar;
public
class
ProgressBarHandlerActivity
extends
Activity {
/** Called when the activity is first created. */
private
Button startButton =
null
;
private
ProgressBar bar =
null
;
int
i=
0
;
@Override
public
void
onCreate(Bundle savedInstanceState) {
super
.onCreate(savedInstanceState);
setContentView(R.layout.main);
startButton = (Button)findViewById(R.id.startButton);
bar = (ProgressBar)findViewById(R.id.bar);
startButton.setOnClickListener(
new
startListener());
}
class
startListener
implements
OnClickListener{
@Override
public
void
onClick(View v) {
// TODO Auto-generated method stub
bar.setVisibility(View.VISIBLE);
handler.post(updateBar);
}
}
// handler内部实现一个匿名内部类,重载消息处理函数
// 当消息从队列中被取出的时候调用handleMessage函数处理消息
// 这样做的好处是使用参数arg1效率比较高
Handler handler =
new
Handler(){
public
void
handleMessage(Message msg){
bar.setProgress(msg.arg1);
handler.post(updateBar);
}
};
Thread updateBar =
new
Thread(){
public
void
run(){
System.out.println(
"Begin Thread!"
);
i=i+
1
;
Message msg = handler.obtainMessage();
msg.arg1=i;
try
{
Thread.sleep(
1000
);
}
catch
(InterruptedException e){
e.printStackTrace();
}
// 发送消息,将消息加入到消息队列中
handler.sendMessage(msg);
if
(i==
100
)
{
handler.removeCallbacks(updateBar);
}
}
};
}
|
注意:用post方法将线程对象放到队列里面执行,并没有开启一个新的线程,而是直接调用线程
对象的run方法,因此并没有实现线程的异步。
解决的办法是先生成一个HandlerThread对象,启动它(start)
使用handlerThread对象的getLooper方法取得其looper对象,注意在此之前必须要start,否则这个
looper是空的
并将looper对象作为参数传递给handler对象,使得这个handler对象绑定到这个Looper所在线程上面
此时需要重写handler类的构造函数,将looper对象传给父类
Looper:类,提供一种循环的从队列当中取得消息的功能,不要自己创建
这样,这个handler就可以循环的从Message消息队列中不断取消息。
下面使用这个办法的代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
|
package
handler.extr;
import
android.app.Activity;
import
android.os.Bundle;
import
android.os.Handler;
import
android.os.HandlerThread;
import
android.os.Looper;
import
android.os.Message;
public
class
HandlerExtrActivity
extends
Activity {
/** Called when the activity is first created. */
@Override
public
void
onCreate(Bundle savedInstanceState) {
super
.onCreate(savedInstanceState);
setContentView(R.layout.main);
// 生成一个HandlerThread对象,此对象实现了使用Looper来处理消息队列的功能
HandlerThread handlerThread =
new
HandlerThread(
"handler-thread"
);
// 启动线程
handlerThread.start();
MyHandler myHandler =
new
MyHandler(handlerThread.getLooper());
Message msg0 = myHandler.obtainMessage();
Bundle b =
new
Bundle();
b.putInt(
"age"
,
25
);
b.putString(
"name"
,
"xiaocheng"
);
msg0.setData(b);
msg0.arg1=
0
;
// 将消息发送到目标对象,所谓目标对象就是生成该msg对象的handler对象
msg0.sendToTarget();
System.out.println(
"Activity--->"
+Thread.currentThread().getId());
}
// 要实现消息的处理则需要继承复写handleMessage方法
// 一旦使用继承,则需要重写构造函数传送Looper参数
class
MyHandler
extends
Handler{
public
MyHandler(){
}
public
MyHandler(Looper looper){
super
(looper);
}
@Override
public
void
handleMessage(Message msg) {
// TODO Auto-generated method stub
int
age = msg.getData().getInt(
"age"
);
String name = msg.getData().getString(
"name"
);
System.out.println(
"handler--->"
+Thread.currentThread().getId());
System.out.println(
"My name is "
+name+
", and my age is "
+age);
System.out.println(
"msg ---- agr1 is "
+msg.arg1);
try
{
Thread.sleep(
1000
);
}
catch
(InterruptedException e){
e.printStackTrace();
}
super
.handleMessage(msg);
}
}
}
|