线程与消息处理

在程序开发时,对于一些比较耗时的操作,我们通常会为其开辟一个单独的线程来执行,这样可以尽可能的减少用户等待的时间。在Android中,默认情况下,所有的操作都是在主线程中进行的,这个主线程负责管理与UI相关的事件,而在我们自己创建的子线程中,又不能对UI组件进行操作,因此,Android提供了消息处理传递机制来解决这一个问题。

1、多线程的常见操作

  1、创建线程。

  在Android中,提供了两种创建线程的方法。(一种是通过Thread类的构造方法创建线程对象,并重写run()方法实现,另一种是通过实现Runnable接口来实现。)

  第一种方法:

  Thread thread=new Thread(new Runnable(){

    @Override

    public void run(){

    //要执行的操作

    }

  })

  第二种方法:

  public class MainActivity extends Activity implement Runnable{

  @Override

  public void run(){

    //要执行的操作

    }

  }

  2、开启线程

  3、线程休眠

  4、中断线程

下面用一个实例来实现上述的这些操作

首先是布局文件:

线程与消息处理
 1 <?xml version="1.0" encoding="utf-8"?>
 2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 3     android:layout_width="fill_parent"
 4     android:layout_height="fill_parent" >
 5 
 6     <Button
 7         android:id="@+id/button1"
 8         android:layout_width="wrap_content"
 9         android:layout_height="wrap_content"
10         android:text="@string/start" />
11 
12     <Button
13         android:id="@+id/button2"
14         android:layout_width="wrap_content"
15         android:layout_height="wrap_content"
16         android:text="@string/stop" />    
17 
18 </LinearLayout>
View Code

然后修改默认的Activity:

线程与消息处理
 1 public class MainActivity extends Activity implements Runnable {
 2     private Thread thread;    //声明线程对象
 3     int i;    //循环变量
 4     
 5     @Override
 6     public void onCreate(Bundle savedInstanceState) {
 7         super.onCreate(savedInstanceState);
 8         setContentView(R.layout.main);
 9         Button startButton=(Button)findViewById(R.id.button1);    //获取“开始”按钮
10         startButton.setOnClickListener(new OnClickListener() {
11             
12             @Override
13             public void onClick(View v) {
14                 i=0;
15                 thread=new Thread(MainActivity.this);    //创建一个线程
16                 thread.start();    //开启线程
17                 
18             }
19         });
20         Button stopButton=(Button)findViewById(R.id.button2);    //获取“停止”按钮
21         stopButton.setOnClickListener(new OnClickListener() {
22             
23             @Override
24             public void onClick(View v) {
25                 if(thread!=null){
26                     thread.interrupt();    //中断线程
27                     thread=null;
28                 }
29                 Log.i("提示:","中断线程");
30                 
31             }
32         });
33     }
34 
35     @Override
36     protected void onDestroy() {
37 
38         if(thread!=null){
39             thread.interrupt();    //中断线程
40             thread=null;
41         }
42         super.onDestroy();
43     }
44     @Override
45     public void run() {
46         while(!Thread.currentThread().isInterrupted()){
47             i++;
48             Log.i("循环变量:",String.valueOf(i));
49         }
50         
51     }
52 }
View Code

接下来运行即可。

 

2、Handler消息传递机制

在上面我们已经介绍了线程相关的知识点,不过此时还没有在新创建的子线程中对UI界面上的内容进行操作,如果用上面的方法进行操作,将会抛出异常。为此,Android中引入了Handler消息传递机制,来实现在新创建的线程中操作UI界面。

首先,我们来了解一个概念,那就是MessageQueue(消息队列)。在Android中,一个线程对应一个Looper对象,而一个Looper对象有对应一个MessageQueue(用于存放message)。

接下来,我们来了解几个类:循环者Looper类,消息处理类Handler,消息类Message。

Looper对象用来为一个线程开启一个消息循环,用来操作MessgeQueue。默认情况下,Android中新创建的线程是没有开启消息循环的。(主线程除外)

 

消息处理类(Handler)允许发送和处理Message和Rannable对象到其所在线程的MessageQueue中。(它主要有两个作用:1、将Message或Runnable应用post()方法或sendMessage()方法发送到MessageQueue中,在发送时可以指定延时时间、发送时间或者要携带的bundle数据。当MessageQueue循环到该Message时,调用相应的Handler对象的handlerMessage()方法对其进行处理。2、在子线程中与主线程进行通信,也就是在工作线程中与UI线程进行通信。)另外,在一个线程中只能有一个Looper和MessageQueue,但是可以有多个Handler,而且这些Handler可以共享一个Looper和MessageQueue。

 

消息类(Message)被存放在MessageQueue中,一个MessageQueue中可以包含多个Message对象。每个Message对象可以通过Messhe.obtain()方法或者Handler.obtainMessage()方法获得。

 

下面我们通过一个简单的实例来了解一下这三者:

布局文件:

线程与消息处理
 1 <?xml version="1.0" encoding="utf-8"?>
 2     <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 3         android:id="@+id/linearLayout1"
 4         android:layout_width="fill_parent"
 5         android:layout_height="fill_parent" >
 6 
 7         <TextView
 8             android:id="@+id/textView1"
 9             android:layout_width="wrap_content"
10             android:layout_height="wrap_content"
11             android:text="开启LooperThread线程" />
12 
13     </LinearLayout>
View Code

新建一个LooperThread类:

线程与消息处理
 1 public class LooperThread extends Thread {
 2      public Handler handler1;    //声明一个Handler对象
 3     @Override
 4     public void run() {
 5         super.run();
 6         
 7         Looper.prepare();    //初始化Looper对象
 8          // 实例化一个Handler对象 
 9         handler1 = new Handler() {
10         public void handleMessage(Message msg) {
11             Log.i("Looper",String.valueOf(msg.what));
12             } 
13         };
14         
15         Message m=handler1.obtainMessage();    //获取一个消息
16         m.what=0x11;    //设置Message的what属性的值
17         handler1.sendMessage(m);    //发送消息
18         Looper.loop();    //启动Looper
19     }
20 }
View Code

在默认MainActivity中:

线程与消息处理
 1 public class MainActivity extends Activity {    
 2 
 3     @Override
 4     public void onCreate(Bundle savedInstanceState) {
 5         super.onCreate(savedInstanceState);
 6         setContentView(R.layout.main);
 7         LooperThread thread=new LooperThread();    //创建一个线程
 8         thread.start();    //开启线程
 9     }
10 
11 
12 }
View Code

运行即可。

 

 

以上三个类关系密切并且方法较多,建议大家参考开发文档详细了解:

Looper:http://developer.android.com/intl/zh-cn/reference/android/os/Looper.html

Handler:http://developer.android.com/intl/zh-cn/reference/android/os/Handler.html

message:http://developer.android.com/intl/zh-cn/reference/android/os/Message.html

此外,还有对其三者进行源码分析的一些相关的博客:

http://www.cnblogs.com/zhaoxiaowei/category/568256.html

 

线程与消息处理,布布扣,bubuko.com

线程与消息处理

上一篇:ajax


下一篇:[C#] 常用工具类——应用程序属性信息访问类