相关文章
Android消息队列机制
IntentService中的耗时操作
文章目录
文章将带你理解 Looper、Handler、Message三者的关系。
一、基本用法
延时应用
定时器应用
//一个定时器
private Handler handler = new Handler();
private Runnable myRunnable= new Runnable() {
public void run() {
if (run) {
handler.postDelayed(this, 1000);
count++;
}
tvCounter.setText("Count: " + count);
}
};
//然后在其他地方调用
handler.post(myRunnable);
handler.post(myRunnable,time);
new Thread(new Runnable() {
@Override
public void run() {
//在子线程post一个Runnable对象
handler.post(new Runnable() {
@Override
public void run() {
//这里是消息处理的方法
//这里运行在主线程。
}
});
}
}).start();
一个线程发送消息,另外一个线程接收信息
//在主线程创建一个Handler对象。
//重写Handler的handleMessage方法,这个就是接收并处理消息的方法。
Handler handler = new Handler(){
@Override
public void handleMessage(Message msg) {
//msg就是子线程发送过来的消息。
}
};
//开启一个子线程
new Thread(new Runnable() {
@Override
public void run() {
//在子线程发送一个消息。
Message msg = new Message();
handler.sendMessage(msg);
}
}).start();
//声明Handler;
Handler handler;
new Thread(new Runnable() {
@Override
public void run() {
//创建当前线程的Looper
Looper.prepare();
//在子线程创建handler对象
handler = new Handler() {
@Override
public void handleMessage(Message msg) {
//这里是消息处理,它是运行在子线程的
}
};
//开启Looper的消息轮询
Looper.loop();
}
}).start();
mBanner.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//在主线程发送一个消息到子线程
Message msg = new Message();
handler.sendMessage(msg);
}
});
//退出轮询
Looper.myLooper().quit();
Looper.myLooper().quitSafely();
获取主线程
Looper.getMainLooper()是获取主线程消息队列。
new Thread(new Runnable() {
@Override
public void run() {
//获取主线程的Looper
Looper looper = Looper.getMainLooper();
//用主线程的Looper创建Handler
handler = new Handler(looper) {
@Override
public void handleMessage(Message msg) {
//这里是运行在主线程的
}
};
}
}).start();
取消某个消息
handler.removeCallbacksAndMessages(null); //取消所有的回调方法和message
二、原理
Message
\frameworks\base\core\java\android\os\Message.java
public final class Message implements Parcelable {
/**
* User-defined message code so that the recipient can identify
* what this message is about. Each {@link Handler} has its own name-space
* for message codes, so you do not need to worry about yours conflicting
* with other handlers.
*/
public int what;
/**
* arg1 and arg2 are lower-cost alternatives to using
* {@link #setData(Bundle) setData()} if you only need to store a
* few integer values.
*/
public int arg1;
/**
* arg1 and arg2 are lower-cost alternatives to using
* {@link #setData(Bundle) setData()} if you only need to store a
* few integer values.
*/
public int arg2;
/**
* An arbitrary object to send to the recipient. When using
* {@link Messenger} to send the message across processes this can only
* be non-null if it contains a Parcelable of a framework class (not one
* implemented by the application). For other data transfer use
* {@link #setData}.
*
* <p>Note that Parcelable objects here are not supported prior to
* the {@link android.os.Build.VERSION_CODES#FROYO} release.
*/
public Object obj;
/**
* Optional Messenger where replies to this message can be sent. The
* semantics of exactly how this is used are up to the sender and
* receiver.
*/
public Messenger replyTo;
/**
* Optional field indicating the uid that sent the message. This is
* only valid for messages posted by a {@link Messenger}; otherwise,
* it will be -1.
*/
public int sendingUid = -1;
/** If set message is in use.
* This flag is set when the message is enqueued and remains set while it
* is delivered and afterwards when it is recycled. The flag is only cleared
* when a new message is created or obtained since that is the only time that
* applications are allowed to modify the contents of the message.
*
* It is an error to attempt to enqueue or recycle a message that is already in use.
*/
/*package*/ static final int FLAG_IN_USE = 1 << 0;
/** If set message is asynchronous */
/*package*/ static final int FLAG_ASYNCHRONOUS = 1 << 1;
/** Flags to clear in the copyFrom method */
/*package*/ static final int FLAGS_TO_CLEAR_ON_COPY_FROM = FLAG_IN_USE;
/*package*/ int flags;
/*package*/ long when;
/*package*/ Bundle data;
/*package*/ Handler target;
/*package*/ Runnable callback;
// sometimes we store linked lists of these things
/*package*/ Message next;
private static final Object sPoolSync = new Object();
private static Message sPool;
private static int sPoolSize = 0;
private static final int MAX_POOL_SIZE = 50;
private static boolean gCheckRecycle = true;
public static Message obtain() {
synchronized (sPoolSync) {
//如果消息池里面有空闲的消息可以用,则用消息池里面的。
if (sPool != null) {
//当前这条信息取自消息池里面的复用
Message m = sPool;
//取出消息池的下一条未用信息
sPool = m.next;
//当前这条链路掐断
m.next = null;
m.flags = 0; // clear in-use flag
//消息池内信息减1
sPoolSize--;
return m;
}
}
return new Message();
}
/**
* Same as {@link #obtain()}, but copies the values of an existing
* message (including its target) into the new one.
* @param orig Original message to copy.
* @return A Message object from the global pool.
*/
public static Message obtain(Message orig) {
Message m = obtain();
m.what = orig.what;
m.arg1 = orig.arg1;
m.arg2 = orig.arg2;
m.obj = orig.obj;
m.replyTo = orig.replyTo;
m.sendingUid = orig.sendingUid;
if (orig.data != null) {
m.data = new Bundle(orig.data);
}
m.target = orig.target;
m.callback = orig.callback;
return m;
}
/**
* Same as {@link #obtain()}, but sets the value for the <em>target</em> member on the Message returned.
* @param h Handler to assign to the returned Message object's <em>target</em> member.
* @return A Message object from the global pool.
*/
public static Message obtain(Handler h) {
Message m = obtain();
m.target = h;
return m;
}
/**
* Same as {@link #obtain(Handler)}, but assigns a callback Runnable on
* the Message that is returned.
* @param h Handler to assign to the returned Message object's <em>target</em> member.
* @param callback Runnable that will execute when the message is handled.
* @return A Message object from the global pool.
*/
public static Message obtain(Handler h, Runnable callback)