安卓011线程&Handler

来源:互联网 发布:三星门锁app软件 编辑:程序博客网 时间:2024/06/05 09:04

一、  多线程
在现实生活中,很多事情都是同时进行的,例如,大家可以一边看书,一边喝咖啡,而计算机可以
一喧播放音乐,一边打印文档.对于这种可以同时进行的任务,就可以用线程来表标,每个纯种

完成一个任务,并与其他线程同时执行,这种机制被称为多线程.


创建线程


1,通过 Thread 类的构造方法创建线程
Public class MyThread extents Thread{
Public void run()
{
}

}


2,通过实现 runnale 接口,
Public class MyThread implements Runnable{public void run(){}}
开启线程:start();

线程休眠:sleep(long time);


二、 Handler  消息传递机制
上面我们讲了如何创建,开启,休眠,中断线程.不过.还没有在新的创建的子线程中对 UI界
面进行操作,如果应用前面介绍的方法对 UI 界面进行操作,将会出错, Only the original thread
that created a view hierarchy can touch its views 的异常,主要原因是 Android 的相关 View 和控
件不是线程安全的,我们必须做独立的处理这点比 J2ME 麻烦一些,这里 Android 给我们提
供了很多方法,有关线程的,我们需要了解下 J2ME 中一些传统的线程创建方法

需要通过 Handler 告诉主线程,让主线程去改变页面的显示


2.1.  消息处理类,Handler  简介
消息处理类(Handler)允许发送和处理 Message 或 Runnable 对象到其后在的线程的

MessageQueue 中。Handler 有以下两个主要作用、


1, 将 Message或 Runnable应用 post()方法或 sendMessage()方法发送到 Message Queue
中,在发送时可以指定延迟时间,发送时间或者要携带的 Bundle 数据,当
MessageQueue 循环到该 Message 时,调用相应的 Handler 对象的 handlerMessage()

方法对其进行处理


2, 在子线程中与主线程进行通信,也就是在工作线程中与 UI 线程进行通信
Handler 类提供的常用的发送和处理消息的方法
方法  描述
handlerMessage(Message msg)  处理消息的方法,通常重写该方法来处理消
息 ,在发送消息 时,该方法会自动回调
post(Runnable r)  立即发送 Runnable 对象,该 Runnable 对象
最后将被封装成 Message 对象
postAtTime(Runnable r,long uptimeMillis)  定时发送 Runnable 对象,该 Runnable 对象
最后将被封装成 Message 对象
postDelayed(Runnable r,long delayMillis)  延迟多少毫秒发送 Runnable 对象,该
Runnable 对象最后将被封装成 Message 对

sendEmptyMessage(int what)  发送空消息
sendMessage(Message msg)  立即发送消息
sendMessageAtTime(Message  msg,long
uptimeMillis)
定时发送消息
sendMessageDelayed(Message  msg,long
delayMillis)
延迟多少毫秒发送消息

使用


1.发送消息
定义一个 Message 对象
①sendMessage(message);
② sendMessageAtTime(message, 绝 对 时 间 ); 使 用 绝 对 时 间 时 需 要 配 合
SystemClock.uptimeMillis()方法
③sendMessageDelayed(message,相对时间);
④sendEmptyMessage(what);在不需要 message 而仅传递一个整型变量消息时,可以使用该方


2.处理消息
①创建一个类,继承 Handler
②重写 handleMessage(Message msg)方法
可以利用 msg 对象,获得传递过来的消息对应的值,具体对应值包括:
msg.arg1-->整型
msg.arg2-->整型
msg.obj--->Object

msg.what->整型,一般用于 sendEmptyMessage()方法


2.2.  消息类 Message  简介
消息类(Message)被存放在 MessageQueue 中,一个 MessageQueue 中可以包含多个 Message
对象,每个 Message 对象可以通过 Message.obtain()方法或者 Handler.obtainMessage()方法或
得,一个 Message 对象具有如
属性性  类型  描述
arg1  Int  用来存放整型数据
arg2  Int  用来存放整型数据
obj  Object  用来存放发送给接收器的 Object 类型的任意对象
replayTo  Messenger  用来指定此 Message 发送到何处的可选 Messager 对象
what  int  用于指定用户自定义的消息代码,这样接收者可以了解这
个消息的信息
注意:使用 Message 类的属性可以携带 int 类型数据,如果要携带其它类型的数据,可以先
将要携带的数据保存到 Bundle 对象中。然后通过 Message 类的 setDate()方法将其添加到
Message 中。
总结:
尽管 Message 有 public 的默认构造方法,但是通常情况下,需要使用 Message.obtain()方法
或 Handler.obtainMessage()方法来从消息池中获得空消息对象,以节省资源。
如果一个 Message 只需要携带简单的 int 型信息,应优先使用 Message.arg1 和 Message.arg2
属性来传递信息,这比用 Bundle 更省内存。

尽可能使用 Message.what 来标识信息,以便用不同方式处理 Message


2.3.  循环者 Looper 及 及 MessageQueue  简介
MessageQueue 概念
在 Android 中,一个线程对应一个 Looper 对象,而一个 Looper 对象又对应一个
MessageQueue(消息队列).MessageQueue用于存放Message,在MessageQueue中,存放的消息
按先进先出的原则执行,MessageQueue 被封装到 Looper 里面了
默认情况下 Android 中新创建的线程是 没有开启消息循环的,主线程除外
如果想要在非主线程中创建 Handler 对象,首先要使用 Looper 类的 prepare()方法来初始化一
个 Looper 对象.然后创建这个 Handler 对象,再使用 Looper 类的 loop 方法,启动 Looper,从消息
队列里获取和处理消息
class MyThread extends Thread{
@Override
public void run() {
super.run();
Looper.prepare();
handler = new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
System.out.println("arg1-->" + msg.arg1);
}
};
Looper.loop();
System.out.println("finish");
}
}
Looper 类提供的常用方法
方法  描述
prepare()  用于初始化 Looper
loop()  调用 loop()方法后,Looper 线程就开始真正
工作了,它会从消息队列里获取和处理消息
myLooper()  可以获取当前线程的 Looper 对象
getThread()  用于获取 Looper 对象所属的线程
quit()  用于结束 Looper 循环
注意,写在 Looper.loop()之后的代码不会被执行,这个函数的内部是一个循环,当调用

Handler.getLooper().quit()方法后,loop()方法才会中止,其后的代码才能得以运行.


三、  总结
Message :消息,其中包含了消息 ID,消息处理对象以及处理的数据等,由 MessageQueue
统一列队,终由 Handler 处理。
Handler  : 处 理 者 , 负 责 Message 的 发 送 及 处 理 。 使 用 Handler 时 , 需 要 实 现
handleMessage(Message msg)方法来对特定的 Message 进行处理,例如更新 UI 等。
MessageQueue :消息队列,用来存放 Handler 发送过来的消息,并按照 FIFO 规则执行。当
然,存放 Message 并非实际意义的保存,而是将 Message 以链表的方式串联起来的,等待
Looper 的抽取。
Looper :消息泵,不断地从 MessageQueue 中抽取 Message 执行。因此,一个 MessageQueue
需要一个 Looper。
Thread :线程,负责调度整个消息循环,即消息循环的执行场所。
其它 小结
①:Handler 的处理过程运行在创建 Handler 的线程里
②:一个 Looper 对应一个 MessageQueue
③:一个线程对应一个 Looper
④:一个 Looper 可以对应多个 Handler

⑥:不确定当前线程时,更新 UI 时尽量调用 post 方法


四、  关系图


五、  更新 UI  的其它方法
 Activity.runOnUiThread(Runnable)
 View.post(Runnable)
 View.postDelayed(Runnable, long)
 Handler
0 0
原创粉丝点击