android message.obj和obtainMessage的区别

android开发教程深入剖析Android消息机制_百度文库
两大类热门资源免费畅读
续费一年阅读会员,立省24元!
将教育做到极致的高端在线教育网站
评价文档:
android开发教程深入剖析Android消息机制
a​n​d​r​o​i​d​开​发​教​程​深​入​剖​析​A​n​d​r​o​i​d​消​息​机​制
阅读已结束,如果下载本文需要使用
想免费下载本文?
你可能喜欢多线程,主线程与子线程的通信Handler&Message&sendmessage与handlemessage&obtainmessage
被android的线程搞的有点晕,今天去问了下高人,有点理解了,现在有快点记记吧。
android是单线程的,在子线程中是不能修改UI线程的任何操作,所以要用一种方式让子线程中的信息返回到主线程中再做修改。这就要让主线程与子线程通信。
那如何让它们之间进行通信呢?我们用Handler这个类。Handler操作的是Message。在主线程中,消息队列是在程序启动时就自动生成的,而子线程要自己手动建立消息队列
,Looper是用来管理消息队列的。
那么什么才是关键呢?首先,要明白Handler都是在主线程中的,也就是说,Handler类就都在主线程中运行,通俗的说就是“绑定”在主线程中。第二,Handler的触发是通过SendMessage()这个方法驱动的,注意,sendMessage
和 handleMessage这一对,一个负责发一个负责收。是哪个Handler发出的,就由哪个Handler去接收。这样msg
就不会混乱了。第三,开启一个线程唯一的方式就是执行start()方法。而只执行run()方法的,线程还是运行在主线程中。如图:
而我们要的是这样的,如图:
要让主线程与子线程通信,则用Handler 操作Message.如图:
好了看下代码吧,分享下:
MainActivity:
package com.
import android.app.A
import android.os.B
import android.os.H
import android.os.L
import android.os.M
import android.util.L
import android.view.V
import android.view.View.OnClickL
import android.widget.B
import android.widget.TextV
public class MainActivity extends Activity {
&private Handler mMainHandler,
&private TextV
&private B
&@Override
&public void onCreate(Bundle savedInstanceState)
&&super.onCreate(savedInstanceState);
&&setContentView(R.layout.main);
&&tv = (TextView)
findViewById(R.id.tv);
&&b = (Button)
findViewById(R.id.btn);
&&Log.i("tag",Thread.currentThread().getName());
&&mMainHandler = new Handler()
&&&@Override
&&&public void
handleMessage(Message msg) {
&&&&Log.i("tag",Thread.currentThread().getName());
&&&&//Log.i("TAG",
"Got an incoming message from the child thread - "
(String) msg.obj);
&&&&tv.setText((String)
&&&&super.handleMessage(msg);
ChildThread().start();
&&b.setOnClickListener(new
View.OnClickListener() {
void onClick(View v) {
(mChildHandler != null) {
&&&&&Log.i("tag",Thread.currentThread().getName());
&&&&&Message
childmsg = mChildHandler.obtainMessage();
&&&&&childmsg.obj
= mMainHandler.getLooper().getThread()
&&&&&&&.getName()
" hello!,This is mainactivity";
&&&&&mChildHandler.sendMessage(childmsg);
&&&&&Log.i("TAG",
"Send a message to the child thread - "
(String) childmsg.obj);
&@Override
&protected void onDestroy() {
&&Log.i("TAG", "Stop looping the
child thread's message queue");
&&mChildHandler.getLooper().quit();
&&super.onDestroy();
&private class ChildThread extends Thread {
&&@Override
&&public void run() {
&&&this.setName("childthread");
&&&Looper.prepare();
&&&mChildHandler
= new Handler() {
&&&&@Override
&&&&public
void handleMessage(Message msg) {
&&&&&Log.i("TAG",
&&&&&&&"Got
an incoming message from the main thread - "
&&&&&&&&&+
(String) msg.obj);
&&&&&&sleep(10000);
&&&&&&Message
toMain = mMainHandler.obtainMessage();
&&&&&&toMain.obj
= "this is"
this.getLooper().getThread().getName()
". do you send me" + (String) msg.obj + "?";
&&&&&&mMainHandler.sendMessage(toMain);
&&&&&&Log.i("TAG",
"Send a message to the main thread - "
(String) toMain.obj);
catch (InterruptedException e) {
&&&&&&e.printStackTrace();
&&&&&super.handleMessage(msg);
&&&Log.i("TAG",
"Child handler is bound to - "
mChildHandler.getLooper().getThread().getName());
&&&Looper.loop();
andriod提供了 Handler 和 Looper
来满足线程间的通信。例如一个子线程从网络上下载了一副图片,当它下载完成后会发送消息给主线程,这个消息是通过绑定在主线程的Handler来传递的。
&* 在Android
,这里的线程分为有消息循环的线程和没有消息循环的线程,有消息循环的线程一般都会有一个Looper,这个是android的新概念。我们的主线程
&* (UI线程)就是一个消息循环的线程
。针对这种消息循环的机制,我们引入一个新的机制Handler,我们有消息循环,就要往消息循环里面发送相应的消息,自定义消息一般都会有自己对应的处理
,消息的发送和清除,把这些都封装在Handler里面,注意Handler只是针对那
些有Looper的线程,不管是UI线程还是子线程,只要你有Looper,我就可以往你的消息队列里面添加东西,并做相应的处理。
但是这里还有一点,就是只要是关于UI相关的东西,就不能放在子线程中,因为子线程是不能操作UI的,只能进行数据、系统等其他非UI的操作。
一个Handler的创建它就会被绑定到这个线程的消息队列中,如果是在主线程创建的,那就不需要写代码来创建消息队列了,默认的消息队列会在主线程被创建。
&* 但是如果是在子线程的话,就必须在创建Handler之前先初始化线程的消息队列。
已投稿到:
以上网友发言只代表其个人观点,不代表新浪网的观点或立场。Android Message和obtainMessage的区别_百度知道
Android Message和obtainMessage的区别
提问者采纳
  从整个Messge池中返回一个新的Message实例,在许多情况下使用它,因为它能避免分配新的对象。  如果是这人的话,那么通过调用obtainMessage方法获取Message对象就能避免创建对象,从而减少内存的开销了。
来自团队:
其他类似问题
为您推荐:
android的相关知识
等待您来回答
下载知道APP
随时随地咨询
出门在外也不愁android线程通信 Message类中的私有变量Runnable callback的作用?
Handler中post方法:&br&public final boolean post(Runnable r) {&br&
return sendMessageDelayed(getPostMessage(r), 0);&br&}&br&调用getPostMessage(r)方法将Runnable转成一个Message。&br&获取一个空消息Message.obtain(),然后将Message中的callback的值设置Runnable r&br&private final Message getPostMessage(Runnable r) {&br&
Message m = Message.obtain();&br&
m.callback =&br&&br&}&br&View.post(Runnable r) 也是调用UI线程的handler.post(r);&br&源代码:&br&&ol&&li& public boolean post(Runnable action) {&/li&&li&
final AttachInfo attachInfo = mAttachI&/li&&li&
if (attachInfo != null) {&/li&&li&
return attachInfo.mHandler.post(action);&/li&&li&
}&/li&&li&
// Assume that post will succeed later&/li&&li&
ViewRootImpl.getRunQueue().post(action);&/li&&li&&/li&&li&
}&/li&&/ol&例:&br&textview.post(new Runnable(){&br&
@Override&br&
public void run() {&br&
textview.setText(&textview&);&br&
}&br&}); &br&&p&handler.post(new Runnable(){&/p&
@Override&br&
public void run() {&br&
textview.setText(&textview&);&br&
}&br&});&br&为什么Message中的私有变量Runnable callback线程中可以更改UI线程的组件?
Handler中post方法:public final boolean post(Runnable r) {
return sendMessageDelayed(getPostMessage(r), 0);}调用getPostMessage(r)方法将Runnable转成一个Message。获取一个空消息Message.obtain(),然后将Message中的callback的值设置Runnable rprivate final Message getPostMessage(Runnable r) {
Message m = Message.obtain();
m.callback =}View.post(Runnable r) 也是调用UI线程的handler.post(r);源代码: public boolean post(Runnable action) {
final AttachInfo attachInfo = mAttachI
if (attachInfo != null) {
return attachInfo.mHandler.post(action);
// Assume that post will succeed later…
按投票排序
之前对android的线程消息处理机制没搞懂才会有这种疑问。自问自答,欢迎补充。android的UI线程不是线程安全的,如果有多个线程并发操作UI控件,可能导致线程安全问题。android通过Handler将 Message和Runnable发送给对应的MessageQueue(getPostMessage方法会将Runnable转成Message),Looper管理MessageQueue通过调用loop方法循环消息把消息分给对应的handler来处理,就可以避免多个线程并发操作UI线程的UI控件,这样就不会导致线程不安全。
Android系统会维护一个全局的message池,当用户需要使用message时,可以通过obtain直接获取,而不是自行创建,这样的设计可以避免不必要的资源浪费详细讲解Android中的Message的源码
相信大家对于Android中的Handler是在为熟悉不过了,但是要知道,Handler就其本身而言只是一个壳子,真正在内部起到作用的是Message这个类,对于Message这个类,相信大家也不会陌生,正如大家经常用到的Message.obtain()的方法一样。但是大家又是否知道obtain()方法里面为我们做了哪些操作了,下面我就带领大家进行Message的王国,去一探究竟吧。
首先映入眼帘的是这样的一行代码:
public final class Message implements Parcelable
不用多说,Message实现了Parcelable的接口,也就是说经过Message封装的数据,可以通过Intent与IPC进行传输。既然实现了Parcelable接口,那么在Message方法中必不可少这三个方法:1)writeToParcel 2)describeContents 3)createFromParcel。
下面我们需要关注的四个成员变量分别是:
1)public int what
2)public int arg1
3)public int arg2
4)public Object obj
我们经常是用到这样的几个参数,但是其真实的含义是否真正的理解呢?只要google的内部的注释才是真正的可靠的。
1)用户定义消息的识别码,以便于系统识别出当前的消息是关于什么的。由于每一个Handle对于自己的消息的识别码都有自己的命名空间。所以我们也就不用担心各个不同的Handler之间会存在冲突的情况。
2)其中第二个参数与第三个参数的意义是一样的,注释上是这样说明的,这两个参数,如果用户只是需要传输简单的int类型的数据,相比较于setData(Bundle bundle),代价更低。
3)第四个参数,按照注释上的说明,是这样理解的:这是一个发送给接受者的一个随意的数据,如果使用Messager来进行发送数据进行跨进程的通信,那么当前的obj如果实现了Parcelable就一定不能够为空指针,对于其他的数据的传输,我们一般使用setData方法就可以了。但是需要注意的是,对于高于android.os.Build.VERSION_CODES#FROYO的版本,这里的Parcelable对象是不支持的。
上面的变量讲完了以后,接下来,我们还需要讲解另外的一组常量的定义:
private static final Object sPoolSync = new Object();
private static Message sP
private static int sPoolSize = 0;
//池塘里最大的尺寸
private static final int MAX_POOL_SIZE = 50;
乍一看,大家可能不理解上面四个变量的定义,如果我提醒一下大家,Android中的Message是可以重用的,那么相信大家就能够大致猜测到这四个变量的含义了。
1、第一个变量其实就是充当锁的作用,避免多线程争抢资源,导致脏数据
2、sPool这个变量可以理解为消息队列的头部的指针
3、sPoolSize是当前的消息队列的长度
4、定义消息队列缓存消息的最大的长度。
Ok,到这里,Message的成员变量已经讲解完毕,接下来主要是讲解其中的Api方法。
第一个方法就是大家经常用到的obtain方法,而且不带任何的参数:
public static Message obtain() {
synchronized (sPoolSync) {
if (sPool != null) {
Message m = sP
sPool = m.
sPoolSize--;
return new CustomMessage();
首先为了避免多线程进行争抢资源,给sPoolSync进行加锁。首先判断当前的队列的指针是否为空,如果当前的指针已经不为空,当前的队列的头部的消息就是可以重用并且被取出,那么当前的队列的头指针指向当前的消息的下一个消息,也就是m.next,同时把取出的消息的尾部指针置为null,队列的长度减1.
第二个方法:
public static Message obtain(Message orig) {
Message m = obtain();
m.what = orig.
m.arg1 = orig.arg1;
m.arg2 = orig.arg2;
m.obj = orig.
m.replyTo = orig.replyTo;
if (orig.data != null) {
m.data = new Bundle(orig.data);
m.target = orig.
m.callback = orig.
我们可以看到,这个方法相对于上面的方法多了一个orig的参数,从上面的代码我们可以看到,首先从队列中取出Message的对象,然后对其中的参数的对象的各个数据进行逐一的拷贝,并最终返回对象。
第三个方法如下:
public static Message obtain(Handler h) {
Message m = obtain();
m.target =
不用多说,这个函数中为当前创建的消息指定了一个Handler对象,因为我们知道Handler是Message的最终的目的地。
public static Message obtain(Handler h, Runnable callback) {
Message m = obtain();
m.target =
m.callback =
相对于上面的方法,这里面多了一行m.callback = callback,按照注释上面的说明,当一些消息真正的被执行的时候,callback这个Runnbale方法将会被触发执行的。
接下来有一系列的方法的逻辑是差不多的,我们取其中的一个进行讲解:
public static Message obtain(Handler h, int what, int arg1, int arg2) {
Message m = obtain();
m.target =
m.arg1 = arg1;
m.arg2 = arg2;
也就是说创建一个Message的时候,顺便可以为这个Message提供一些逻辑上需要的参数。
消息有创建,那么就必然存在回收的概念,下面我们一起来看一下:
public void recycle() {
clearForRecycle();
synchronized (sPoolSync) {
if (sPoolSize & MAX_POOL_SIZE) {
sPoolSize++;
void clearForRecycle() { flags = 0; what = 0; arg1 = 0; arg2 = 0; obj = replyTo = when = 0; target = callback = data = }
在clearForRecycle这个函数中,是做一些回收的预处理的操作,该置为0的参数置为0,该置为null的参数置为null。在recycle的函数中,只要当前的缓存的队列的长度没有超过上限,将当前的消息添加到队列的尾部。
下面的方法是关于实现Parcelable所需要的方法:
public static final Parcelable.Creator CREATOR
= new Parcelable.Creator() {
public Message createFromParcel(Parcel source) {
Message msg = Message.obtain();
msg.readFromParcel(source);
public Message[] newArray(int size) {
return new Message[size];
public int describeContents() {
public void writeToParcel(Parcel dest, int flags) {
if (callback != null) {
throw new RuntimeException(
&Can't marshal callbacks across processes.&);
dest.writeInt(what);
dest.writeInt(arg1);
dest.writeInt(arg2);
if (obj != null) {
Parcelable p = (Parcelable)
dest.writeInt(1);
dest.writeParcelable(p, flags);
} catch (ClassCastException e) {
throw new RuntimeException(
&Can't marshal non-Parcelable objects across processes.&);
dest.writeInt(0);
dest.writeLong(when);
dest.writeBundle(data);
Messenger.writeMessengerOrNullToParcel(replyTo, dest);
private void readFromParcel(Parcel source) {
what = source.readInt();
arg1 = source.readInt();
arg2 = source.readInt();
if (source.readInt() != 0) {
obj = source.readParcelable(getClass().getClassLoader());
when = source.readLong();
data = source.readBundle();
replyTo = Messenger.readMessengerOrNullFromParcel(source);
Ok,Message的内核的剖析就讲解到这里,相信大家以后再用到这个类的时候会有更深的理解啦。
您对本文章有什么意见或着疑问吗?请到您的关注和建议是我们前行的参考和动力&&
您的浏览器不支持嵌入式框架,或者当前配置为不显示嵌入式框架。

我要回帖

更多关于 android中的message 的文章

 

随机推荐