线程:Message和Runnable

程序需要相应用户的操作,最要能在200ms(0.2s)之内,如果超过5秒没有反应,ActivityManager会没有提示就kill了 activity。然而,activity可能真的需要时间来进行处理,这往往会用到后台线程-background thread。后台线程可以安全 地和UI线程进行交互,其中后台线程是不能修改UI的。
通过创建一个Handler子类的对象,每个acvivity只需一个Handler对象。后台进程可通过两种方式Handler进行通信:message和Runnable对象,其结果实质都是将在Handler的队列中放入内容,message是放置信息,可以传递一些参数,Handler获取这些信息并将判度如何处理,而Runnable则是直接给出处理的方法。
这些队列中的内容(无论Message还是Runnable)可以要求马上执行,延迟一定时间执行或者指定某个时刻执行,如果将他们放置在队列头,则表示具有最高有限级别,立即执行。这些函数包括有:sendMessage(), sendMessageAtFrontOfQueue(), sendMessageAtTime(), sendMessageDelayed()以及用于在队列中加入Runnable的post(), postAtFrontOfQueue(), postAtTime(),postDelay()。
一般而言,推荐是Messge方式,这样程序设计得可以更为灵活,而Runnable在某些简单明确的方式中使用。我们将通过三种方法编写一个小例子来学习。这个例子是一个进度条,每隔1秒,进度条步进5,如果acvity停止时,进度条归零。
Android XML :
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout ...... />
<ProgressBar android:id="@+id/c15_progress"
style="?android:attr/progressBarStyleHorizontal" <!-- 这表明采用传统水平进度条的方式-->
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
</LinearLayout>
例子一:线程开启,采用Message传递后台线程和UI主线程之间的信息
public class Chapter15Test1 extends Activity{
private ProgressBar bar = null;
private boolean isRunning = false;

/* 我们为这个Acivity创建一个用于和后台程序通信的handler,简单地,只要一收到message,就将progressbar进度增加5。*/
/* 步骤1:创建Handler,并通过handleMessage()给出当收到消息是UI需要进行如何处理,例子简单不对msg的内容进行分析*/
Handler handler= new Handler(){
public void handleMessage (Message msg) {
bar.incrementProgressBy(5);
}
};

protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.chapter_15_test1);
bar=(ProgressBar)findViewById(R.id.c15_progress);
}

/*on Start是UI初始化并显示时调用*/
protected void onStart() {
super.onStart();
bar.setProgress(0);
/*步骤2:建立后台线程处理,采用Thread,其中run()的内容,就是线程并行处理的内容,Thread是Runnable的implements*/
Thread background = new Thread(new Runnable(){
public void run () {
try{
for(int i = 0; i < 20 && isRunning; i ++){
Thread.sleep(1000);
/* 步骤2.1:发送Message到队列中,参数中的obtainMessage()是用于给出一个新Message,本例无参数,对应的在handler在队列中收到这条消息时,则通过handleMessage()进行处理*/
handler.sendMessage (handler.obtainMessage ());
}
}catch(Throwable t){
//jest end the thread
}
}

});
isRunning = true;
/*步骤3:启动线程*/
background.start();
}

/*onStop是UI停止显示时调用,例如我们按了返回键*/
protected void onStop() {
super.onStop();
isRunning = false;
}
}
例子2:采用Runnable
我们在上面的例子的基础上进行修改,如下
/*步骤1:由于不需要处理Message,也即不需要处理handleMessage()*/
Handler handler= new Handler();
/*步骤1.1:定义处理动作,采用Runnable的实例,通过implements run()来定制处理,这里是简单将进度条步进5。由于我们将在Thread中使用这个实例,所以考虑采用final的方式*/
final Runnable r = new Runnable() {
public void run(){
bar.incrementProgressBy(5);
}
};
/* ... ...在onStart()中的步骤2:线程的处理,和提供message不同,对于runnable方式,采用post */
Thread background = new Thread(new Runnable(){
public void run() {
try{
for(int i = 0; i < 20 && isRunning; i ++){
Thread.sleep(1000);
handler.post(r);
}
}catch(Throwable t){
//jest end the thread
}
}
});
background.start();
例子3:可以用延迟处理实现定时触发,让程序更为简单
在这里例子,事实我们是进行定时的处理,利用Handler队列可以设置延期处理的方式,我们并不需要创建一个后台运行的线程,也可以实现
Handler handler= new Handler();

... ... 在onStart() ... ...
//利用handler.postDelayed(r,1000),在队列中加入1秒后,进行r的处理,而在r的处理中,最后在handler的队列中加入一个延迟1秒的处理,如是,就可以每隔1秒进行一次处理。
handler.postDelayed(new Runnable() {
public void run() {
if(isRunning && Chapter15Test2.step < 20){
step ++;
bar.incrementProgressBy(5);
handler.postDelayed(this, 1000);
}
}
},1000 );
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值