在程序开发时,对于一些比较耗时的操作,我们通常会为其开辟一个单独的线程来执行,这样可以尽可能的减少用户等待的时间。在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>
然后修改默认的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 }
接下来运行即可。
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>
新建一个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 }
在默认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 }
运行即可。
以上三个类关系密切并且方法较多,建议大家参考开发文档详细了解:
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