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

1、多线程的常见操作

  1、创建线程。

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

  第一种方法:

  Thread thread=new Thread(new Runnable(){

    @Override

    public void run(){

    //要执行的操作

    }

  });

  thread.start();

  第二种方法:

  public class MainActivity extends Activity implement Runnable{

  @Override

  public void run(){

    //要执行的操作

    }

  }

  2、开启线程

  3、线程休眠

  4、中断线程

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

首先是布局文件:

 <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent" > <Button
android:id="@+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/start" /> <Button
android:id="@+id/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/stop" /> </LinearLayout>

然后修改默认的Activity:

 public class MainActivity extends Activity implements Runnable {
private Thread thread; //声明线程对象
int i; //循环变量 @Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Button startButton=(Button)findViewById(R.id.button1); //获取“开始”按钮
startButton.setOnClickListener(new OnClickListener() { @Override
public void onClick(View v) {
i=0;
thread=new Thread(MainActivity.this); //创建一个线程
thread.start(); //开启线程 }
});
Button stopButton=(Button)findViewById(R.id.button2); //获取“停止”按钮
stopButton.setOnClickListener(new OnClickListener() { @Override
public void onClick(View v) {
if(thread!=null){
thread.interrupt(); //中断线程
thread=null;
}
Log.i("提示:","中断线程"); }
});
} @Override
protected void onDestroy() { if(thread!=null){
thread.interrupt(); //中断线程
thread=null;
}
super.onDestroy();
}
@Override
public void run() {
while(!Thread.currentThread().isInterrupted()){
i++;
Log.i("循环变量:",String.valueOf(i));
} }
}

接下来运行即可。

上面只是线程的简单操作。这里推荐一篇写得比较详细的文章:《java中的多线程

2、异步消息处理机制

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

首先,我们来了解一些概念。

什么是异步?

简单来说,就是A和B两个人可以同时做两种事,也就是分别做自己的事。(而不是A做完事后B才开始做事)

什么是消息处理机制?

就应用程序而言,Android系统中JAVA的应用程序和其他系统上相同,都是靠消息驱动来工作的,他们大致的工作原理如下:

1、有一个消息队列,可以往这个消息队列中投递消息。

2、有一个消息循环,不断从消息队列中取出消息,然后处理。

在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()方法获得。

关系如下图:

(图片来源于网络)

下面我们做一个简单的实例。(从子线程获取的数据更新到UI)

布局文件如下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<Button
android:id="@+id/btn"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="点击改变下方界面"/>
<TextView
android:id="@+id/tv"
android:layout_marginTop="50dp"
android:layout_gravity="center"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="数据没改变前"/> </LinearLayout>

java代码如下:

public class MainActivity extends Activity {

    private TextView tv;

    @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button btn=(Button) findViewById(R.id.btn);
tv = (TextView) findViewById(R.id.tv);
btn.setOnClickListener(new OnClickListener() { @Override
public void onClick(View v) {
new Thread(new Runnable() { @Override
public void run() {
Message msg=new Message();
msg.obj="您已点击按钮,数据发生改变";//message的内容
msg.what=1;//指定message
handler.sendMessage(msg);//handler发送message }
}).start(); }
});
} private Handler handler=new Handler(){
public void handleMessage(Message msg) {
switch (msg.what) {
case 1://获取到what属性为1的message
tv.setText((String)msg.obj);//将message的内容填充到TextView中
break; default:
break;
}
};
}; }

运行程序,结果如下图:

此外,关于异步消息处理机制。除了handler外,常用的还有AsyncTask。关于AsyncTask请看另一篇博文《Android AsyncTask 初探》。

在子线程中更改UI,更多内容请参考我的另一篇博文《Android 在子线程中更新UI》。

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

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

Android线程与异步消息处理机制的更多相关文章

  1. Android线程之异步消息处理机制(三)——AsyncTask

    Android的异步消息处理机制能够很完美的解决了在子线程中进行UI操作的问题,但是为了更加方便我们在子线程中对UI进行操作,Android还提供了另一个很好用的工具,AsyncTask就是其中之一. ...

  2. Android线程之异步消息处理机制(二)——Message、Handler、MessageQueue和Looper

    异步消息处理机制解析 Android中的异步消息处理主要有四个部分组成,Message.Handler.MessageQueue和Looper. 1.Message Message是在线程之间传递的消 ...

  3. Android线程之异步消息处理机制(一)

    Android不允许在子线程中进行UI操作,但是有些时候,我们必须在子线程里去执行一些耗时任务,然后根据任务的执行结果来更新相应的UI控件.对于这种情况,Android提供了一套异步消息处理机制,完美 ...

  4. Android开发之异步消息处理机制AsyncTask

    转自:Android AsyncTask完全解析,带你从源码的角度彻底理解 另外一篇比较详细的博文:http://blog.csdn.net/liuhe688/article/details/6532 ...

  5. Android学习之异步消息处理机制

    •前言 我们在开发 APP 的过程中,经常需要更新 UI: 但是 Android 的 UI 线程是不安全的: 如果想更新 UI 线程,必须在进程的主线程中: 这里我们引用了异步消息处理机制来解决之一问 ...

  6. Android开发之异步消息处理机制Handler

    更加详细的介绍Handler的博文-http://blog.csdn.net/guolin_blog/article/details/9991569 Android中的异步消息处理主要有四个部分组成, ...

  7. Android之Handler(异步消息处理)机制

    1. 概述 Handler . Looper .Message 这三者都与Android异步消息处理线程相关的概念.那么什么叫异步消息处理线程呢?异步消息处理线程启动后会进入一个无限的循环体之中,每循 ...

  8. Android Learning:多线程与异步消息处理机制

    在最近学习Android项目源码的过程中,遇到了很多多线程以及异步消息处理的机制.由于之前对这块的知识只是浅尝辄止,并没有系统的理解.但是工程中反复出现让我意识到这个知识的重要性.所以我整理出这篇博客 ...

  9. Android中Handler的消息处理机制以及源码分析

    在实际项目当中,一个很常见的需求场景就是在根据子线程当中的数据去更新ui.我们知道,android中ui是单线程模型的,就是只能在UI线程(也称为主线程)中更新ui.而一些耗时操作,比如数据库,网络请 ...

随机推荐

  1. javaweb之javascript结合(三)

    1.案例一:在末尾添加节点 第一步:获取到ul标签 第二步:创建li标签 document.createElement("标签名称")方法 第三步:创建文本 document.cr ...

  2. 应用程序连接oracle rac

    10g rac vip漂移的目的不是让client不加改变的连接过来而是让client尽快收到一个连接终止的包,然后由client去连接tnsnames中配置的下一个地址.和没有vip相比, 使用vi ...

  3. POJ 3450 Corporate Identity kmp+最长公共子串

    枚举长度最短的字符串的所有子串,再与其他串匹配. #include<cstdio> #include<cstring> #include<algorithm> #i ...

  4. Windows Azure中对映像的管理及操作

    映像是用作新虚拟机的创建模板的 .vhd 文件.映像是一个模板,因为它与已配置的虚拟机不同,没有计算机名称和用户帐户设置等特定设置.可以通过 Windows Azure 管理门户使用现有映像,或创建您 ...

  5. zabbix 获取不到自定义脚本的值解决

    agent端: zabbix 自定义脚本 [root@localhost script]# cat check_ping.sh #!/bin/bash result=$(/usr/local/nagi ...

  6. chroot 命令实例讲解

    我是一个刚接触 Linux 和 Unix 的新手.我该如何改变一个命令的根目录?我要怎样改变一个进程的根目录呢,比如用 chroot 命令将web服务与文件系统隔离?我要如何使用 chroot 恢复密 ...

  7. 关于Redis的常识(推荐)

    原文出处: https://github.com/springside/springside4/wiki/redis 版本:V3.0.3 2013-8-1 (@江南白衣版权所有,转载请保留出处) 1. ...

  8. 免费安卓IOS测试API接口,后续会陆续增加接口

    各位博友好!开发的安卓或者ios的朋友们,经常会遇到想测试但是没有公开的api接口进行进行测试.但自己又不会开发服务端或者没有服务器,这里我免费提供了一整套API接口.欢迎大家调用,目标是方便大家. ...

  9. Spring3.0 AOP 具体解释

    一.什么是 AOP. AOP(Aspect Orient Programming),也就是面向切面编程.能够这样理解,面向对象编程(OOP)是从静态角度考虑程序结构,面向切面编程(AOP)是从动态角度 ...

  10. hdu1430魔板(BFS+康托展开)

    做这题先看:http://blog.csdn.net/u010372095/article/details/9904497 Problem Description 在魔方风靡全球之后不久,Rubik先 ...