首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 移动开发 > 移动开发 >

线程:Message跟Runnable

2012-09-27 
线程:Message和Runnable程序需要相应用户的操作,最要能在200ms(0.2s)之内,如果超过5秒没有反应,ActivityMa

线程: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 );

热点排行