android中的线程机制

Android中的好多应用,如UI更新,游戏开发,和耗时的操作都需要用到多线程的知识。而对Android中的线程机制好多人多觉得学习有困难。下面我们就一起来学习一下。

谈及Android中的线程我们会涉及到如下几个概念:

1. Handler 2. Looper 3. HandlerThread 4.Message 5. MessageQueue

下面我们由浅入深来探讨一下。我们用Java多线程中很经典的例子计时器为例。我们要编写实现一个计时器,该如何编写呢?按照java中多线程的思路,我们很自然的会这样实现

代码如下:

  1. package xuan.blog.hander;    
  2.     
  3. import android.app.Activity;    
  4. import android.os.Bundle;    
  5. import android.util.Log;    
  6. import android.view.View;    
  7. import android.widget.Button;    
  8. import android.widget.TextView;    
  9.     
  10. public class clockActivity extends Activity {    
  11.     /** Called when the activity is first created. */    
  12.     private String TAG="clockActivity";    
  13.     private Button endButton;    
  14.     private TextView textView;    
  15.     private Thread clockThread;    
  16.     private int timer=0;    
  17.     private boolean isRunning=true;    
  18.     @Override    
  19.     public void onCreate(Bundle savedInstanceState) {    
  20.         super.onCreate(savedInstanceState);    
  21.         setContentView(R.layout.main);    
  22.         endButton=(Button)findViewById(R.id.endBtn);    
  23.         textView=(TextView)findViewById(R.id.textview);    
  24.         endButton.setOnClickListener(new View.OnClickListener() {    
  25.                 
  26.             @Override    
  27.             public void onClick(View v) {    
  28.                 // TODO Auto-generated method stub    
  29.                 isRunning=false;    
  30.             }    
  31.         });    
  32.         clockThread=new Thread(new Runnable(){    
  33.     
  34.             @Override    
  35.             public void run() {    
  36.                 // TODO Auto-generated method stub    
  37.                 while(isRunning){    
  38.                     try{    
  39.                         Thread.currentThread().sleep(1000);    
  40.                         timer++;    
  41.                         textView.setText("走了"+timer+"秒");    
  42.                         Log.d(TAG,"time:"+timer);    
  43.                     }catch(InterruptedException e){    
  44.                         e.printStackTrace();    
  45.                     }    
  46.                 }    
  47.             }});    
  48.         clockThread.start();    
  49.     }    
  50. }    
package xuan.blog.hander;  
  
import android.app.Activity;  
import android.os.Bundle;  
import android.util.Log;  
import android.view.View;  
import android.widget.Button;  
import android.widget.TextView;  
  
public class clockActivity extends Activity {  
    /** Called when the activity is first created. */  
    private String TAG="clockActivity";  
    private Button endButton;  
    private TextView textView;  
    private Thread clockThread;  
    private int timer=0;  
    private boolean isRunning=true;  
    @Override  
    public void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);  
        setContentView(R.layout.main);  
        endButton=(Button)findViewById(R.id.endBtn);  
        textView=(TextView)findViewById(R.id.textview);  
        endButton.setOnClickListener(new View.OnClickListener() {  
              
            @Override  
            public void onClick(View v) {  
                // TODO Auto-generated method stub  
                isRunning=false;  
            }  
        });  
        clockThread=new Thread(new Runnable(){  
  
            @Override  
            public void run() {  
                // TODO Auto-generated method stub  
                while(isRunning){  
                    try{  
                        Thread.currentThread().sleep(1000);  
                        timer++;  
                        textView.setText("走了"+timer+"秒");  
                        Log.d(TAG,"time:"+timer);  
                    }catch(InterruptedException e){  
                        e.printStackTrace();  
                    }  
                }  
            }});  
        clockThread.start();  
    }  
}  

我们用Thread的构造方法创建了一个线程对象,并启动了该线程,在该线程中来计算并更新textView。

然而,在Android中运行我们会发现这样会抛出异常!!

这是因为Android系统中的视图组件并不是线程安全的,在Android中UI的更新必须由主线程来完成。而上面我们违反了这一规则。

我们应该如何解决这个问题呢?我们应该让主线程负责创建,显示和更新UI控件,启动子线程,停止子线程。让子线程完成计算并向主线程发出更新UI的消息让主线程来更新UI。

如何实现子线程和主线程之间的消息传递呢?Android中为我们提供了Handler机制。

Handler是android中多线程间传递消息和计划任务的“工具”类。Handler 会在多个线程中发送Message和Runnable。

andler在多线程中有两方面的应用:

1.发送消息,在不同的线程间发送消息,使用方法sendXXX();

2.计算任务,在未来执行某任务,使用方法postXXX();

一个线程发出消息后,接受消息是通过重写Handler类中的handleMessage(Message)方法实现。

Handler也可以通过postXXX()方法提交计划任务,当取出一个任务Runnable是便会执行其中的run()方法。

经过分析,我们用handler发送消息的应用修改上述代码:

  1. public class clockActivity extends Activity {    
  2.     /** Called when the activity is first created. */    
  3.     private String TAG="clockActivity";    
  4.     private Button endButton;    
  5.     private TextView textView;    
  6.     private Thread clockThread;    
  7.     private int timer=0;    
  8.     private boolean isRunning=true;    
  9.     private Handler handler;    
  10.     @Override    
  11.     public void onCreate(Bundle savedInstanceState) {    
  12.         super.onCreate(savedInstanceState);    
  13.         setContentView(R.layout.main);    
  14.         endButton=(Button)findViewById(R.id.endBtn);    
  15.         textView=(TextView)findViewById(R.id.textview);    
  16.         endButton.setOnClickListener(new View.OnClickListener() {    
  17.                 
  18.             @Override    
  19.             public void onClick(View v) {    
  20.                 // TODO Auto-generated method stub    
  21.                 isRunning=false;    
  22.             }    
  23.         });    
  24.         handler=new Handler(){    
  25.     
  26.             @Override    
  27.             public void handleMessage(Message msg) {    
  28.                 // TODO Auto-generated method stub    
  29.                 super.handleMessage(msg);    
  30.                 switch(msg.what){    
  31.                 case 0:textView.setText("走了"+timer+"秒");    
  32.                 }    
  33.             }    
  34.                 
  35.         };    
  36.         clockThread=new Thread(new Runnable(){    
  37.     
  38.             @Override    
  39.             public void run() {    
  40.                 // TODO Auto-generated method stub    
  41.                 while(isRunning){    
  42.                     try{    
  43.                         Thread.currentThread().sleep(1000);    
  44.                         timer++;    
  45.                         //textView.setText("走了"+timer+"秒");    
  46.                         Message msg=new Message();    
  47.                         msg.obj=timer;    
  48.                         msg.what=0;    
  49.                         handler.sendMessage(msg);    
  50.                         Log.d(TAG,"time:"+timer);    
  51.                     }catch(InterruptedException e){    
  52.                         e.printStackTrace();    
  53.                     }    
  54.                 }    
  55.             }});    
  56.         clockThread.start();    
  57.     }    
  58. }    
public class clockActivity extends Activity {  
    /** Called when the activity is first created. */  
    private String TAG="clockActivity";  
    private Button endButton;  
    private TextView textView;  
    private Thread clockThread;  
    private int timer=0;  
    private boolean isRunning=true;  
    private Handler handler;  
    @Override  
    public void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);  
        setContentView(R.layout.main);  
        endButton=(Button)findViewById(R.id.endBtn);  
        textView=(TextView)findViewById(R.id.textview);  
        endButton.setOnClickListener(new View.OnClickListener() {  
              
            @Override  
            public void onClick(View v) {  
                // TODO Auto-generated method stub  
                isRunning=false;  
            }  
        });  
        handler=new Handler(){  
  
            @Override  
            public void handleMessage(Message msg) {  
                // TODO Auto-generated method stub  
                super.handleMessage(msg);  
                switch(msg.what){  
                case 0:textView.setText("走了"+timer+"秒");  
                }  
            }  
              
        };  
        clockThread=new Thread(new Runnable(){  
  
            @Override  
            public void run() {  
                // TODO Auto-generated method stub  
                while(isRunning){  
                    try{  
                        Thread.currentThread().sleep(1000);  
                        timer++;  
                        //textView.setText("走了"+timer+"秒");  
                        Message msg=new Message();  
                        msg.obj=timer;  
                        msg.what=0;  
                        handler.sendMessage(msg);  
                        Log.d(TAG,"time:"+timer);  
                    }catch(InterruptedException e){  
                        e.printStackTrace();  
                    }  
                }  
            }});  
        clockThread.start();  
    }  
}  

通过这种方式便实现了子线程和主线程之间的通信。当然我们也可以通过Handler的执行计划任务来完成这计时器的功能,代码如下:

  1. public class clockActivity extends Activity {    
  2.     /** Called when the activity is first created. */    
  3.     private String TAG="clockActivity";    
  4.     private Button endButton;    
  5.     private TextView textView;    
  6.     private int timer=0;    
  7.     private boolean isRunning=true;    
  8.     private Handler handler;    
  9.     @Override    
  10.     public void onCreate(Bundle savedInstanceState) {    
  11.         super.onCreate(savedInstanceState);    
  12.         setContentView(R.layout.main);    
  13.         endButton=(Button)findViewById(R.id.endBtn);    
  14.         textView=(TextView)findViewById(R.id.textview);    
  15.         endButton.setOnClickListener(new View.OnClickListener() {    
  16.             @Override    
  17.             public void onClick(View v) {    
  18.                 // TODO Auto-generated method stub    
  19.                 isRunning=false;    
  20.             }    
  21.         });    
  22.         handler=new Handler();    
  23.         Runnable r=new Runnable(){    
  24.     
  25.             @Override    
  26.             public void run() {    
  27.                 // TODO Auto-generated method stub    
  28.                 if(isRunning){    
  29.                     textView.setText("走了"+timer+"秒");    
  30.                     timer++;    
  31.                     handler.postDelayed(this1000);//提交任务r,延时1秒执行    
  32.                 }    
  33.             }    
  34.         };    
  35.         handler.postDelayed(r, 1000);    
  36.         }    
  37. }    
public class clockActivity extends Activity {  
    /** Called when the activity is first created. */  
    private String TAG="clockActivity";  
    private Button endButton;  
    private TextView textView;  
    private int timer=0;  
    private boolean isRunning=true;  
    private Handler handler;  
    @Override  
    public void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);  
        setContentView(R.layout.main);  
        endButton=(Button)findViewById(R.id.endBtn);  
        textView=(TextView)findViewById(R.id.textview);  
        endButton.setOnClickListener(new View.OnClickListener() {  
            @Override  
            public void onClick(View v) {  
                // TODO Auto-generated method stub  
                isRunning=false;  
            }  
        });  
        handler=new Handler();  
        Runnable r=new Runnable(){  
  
            @Override  
            public void run() {  
                // TODO Auto-generated method stub  
                if(isRunning){  
                    textView.setText("走了"+timer+"秒");  
                    timer++;  
                    handler.postDelayed(this, 1000);//提交任务r,延时1秒执行  
                }  
            }  
        };  
        handler.postDelayed(r, 1000);  
        }  
}  

注意运行完handler.postDelayed(r, 1000);只是提交了一次任务,因此为了反复执行要在run()方法中再次提交。注意上述方法中发送任务和执行任务都是在主线程中实现的,我们并没有令启动线程。

在下一篇文章中,我们在具体分析一下Android中的消息机制。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值