您的位置:首页 > 移动开发 > Android开发

android高手进阶教程(一)之--android中的消息机制

2015-09-08 17:51 615 查看

1.1 异步神器Handler

Handler
允许我们在一个线程的消息队列(
MessageQueue
)里面发送、处理
Message
Runnable
,每一个
Handler
只能在一个线程和一个消息队列(
MessageQueue
),当我们创建
Handler
时,这个
Handler
与当前线程和当前线程里面的消息队列(
MessageQueue
)关联,当线程执行操作结束后,
Handler
可以将消息分发出去。

Handler中我们使用频率较高的是
post(Runnable r)
sendMessage(Message msg)
,通过源码我们可以看到都调用了将当前
Message
加入消息队列,然后当前线程的
Looper
通过获取当前的
MessageQueue
获取消息再发送个
Handler
,由
Handler
分发给拥有这个
Handler
的线程(必须是拥有
Handler
的线程)。

/**
* Causes the Runnable r to be added to the message queue.
* The runnable will be run on the thread to which this handler is
* attached.
*
* @param r The Runnable that will be executed.
*
* @return Returns true if the Runnable was successfully placed in to the
*         message queue.  Returns false on failure, usually because the
*         looper processing the message queue is exiting.
*/
public final boolean post(Runnable r)
{
return  sendMessageDelayed(getPostMessage(r), 0);
}

/**
* Pushes a message onto the end of the message queue after all pending messages
* before the current time. It will be received in {@link #handleMessage},
* in the thread attached to this handler.
*
* @return Returns true if the message was successfully placed in to the
*         message queue.  Returns false on failure, usually because the
*         looper processing the message queue is exiting.
*/
public final boolean sendMessage(Message msg)
{
return sendMessageDelayed(msg, 0);
}

/**
* Enqueue a message into the message queue after all pending messages
* before the absolute time (in milliseconds) <var>uptimeMillis</var>.
* <b>The time-base is {@link android.os.SystemClock#uptimeMillis}.</b>
* Time spent in deep sleep will add an additional delay to execution.
* You will receive it in {@link #handleMessage}, in the thread attached
* to this handler.
*
*/
public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
MessageQueue queue = mQueue;
if (queue == null) {
RuntimeException e = new RuntimeException(
this + " sendMessageAtTime() called with no mQueue");
Log.w("Looper", e.getMessage(), e);
return false;
}
return enqueueMessage(queue, msg, uptimeMillis);
}


1.2 Handler 使用实例

public class MainActivity extends Activity {

private ImageView image;
private Handler mHandler = new Handler(){

/**
* 获取子线程中消息队列发送的Message
* @param msg
*/
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
Bitmap bm = (Bitmap) msg.obj;
image.setImageBitmap(bm);
}
};

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
image = (ImageView) findViewById(R.id.image);
new MyThread(mHandler).start();

}

private class MyThread extends Thread{
private Handler mHandler;
public MyThread(Handler handler){
this.mHandler = handler;
}
@Override
public void run() {
//1.耗时操作,比如请求网络
try {
HttpURLConnection connection = (HttpURLConnection) new URL("http://h.hiphotos.baidu.com/image/pic/item/e7cd7b899e510fb300679675da33c895d0430cd1.jpg").openConnection();
connection.setConnectTimeout(5000);
connection.setReadTimeout(20000);
InputStream is = connection.getInputStream();
Bitmap bm = BitmapFactory.decodeStream(is);
//2.结果包装到Message
Message msg = new Message();
msg.obj = bm;
//3.handler将消息发送给主线程(一般式UI线程)
mHandler.sendMessage(msg);
} catch (IOException e) {
e.printStackTrace();
}

}
}

}


1.3 HandlerThread

HandlerThread是一个拥有looper的线程,这个looper可以用来创建handler,启动这个线程需要调用start().

public class HandlerThread extends Thread {
int mPriority;
int mTid = -1;
Looper mLooper;

public HandlerThread(String name) {
super(name);
mPriority = android.os.Process.THREAD_PRIORITY_DEFAULT;
}

/**
* 构造方法
* @param name  thread的name
* @param priority 优先级
*/
public HandlerThread(String name, int priority) {
super(name);
mPriority = priority;
}

/**
* 回调方法,可以被复写
*/
protected void onLooperPrepared() {
}

@Override
public void run() {
//获取线程id
mTid = Process.myTid();

//将当前线程初始化为Looper线程

Looper.prepare();
synchronized (this) {
mLooper = Looper.myLooper();
notifyAll();
}
Process.setThreadPriority(mPriority);
onLooperPrepared();
//开始循环处理消息队列
Looper.loop();
mTid = -1;
}

/**
* 这个方法返回和此线程相关的Looper,如果这个线程没有启动或者isAlive()返回false,Looper将返回null,
* 如果这个线程已经启动,这个方法将会阻塞,一直到looper实例化后。
* @return The looper.
*/
public Looper getLooper() {
if (!isAlive()) {
return null;
}

// If the thread has been started, wait until the looper has been created.
synchronized (this) {
while (isAlive() && mLooper == null) {
try {
wait();
} catch (InterruptedException e) {
}
}
}
return mLooper;
}

public boolean quit() {
Looper looper = getLooper();
if (looper != null) {
looper.quit();
return true;
}
return false;
}

/**
* 停止
* @return
*/
public boolean quitSafely() {
Looper looper = getLooper();
if (looper != null) {
looper.quitSafely();
return true;
}
return false;
}

/**
* 获取线程id
*/
public int getThreadId() {
return mTid;
}
}


2.1 单曲循环Looper

Looper的字面意思就是“循环者”,一个普通线程通过它可以变成一个循环线程,上文中的HandlerThread就是典型的例子,在平时开发中,我们经常需要一个循环线程,一旦有新任务则执行,执行完毕后必须等待下一个任务,这就是Looper线程。使用Looper创建线程也很简单。

class LooperThread extends Thread {
public Handler mHandler;

public void run() {
Looper.prepare();

mHandler = new Handler() {
public void handleMessage(Message msg) {
// 处理消息                }
};
Looper.loop();
}
}


2.2 Looper源码解析

public class Looper {
// 每个线程中的Looper对象其实是一个ThreadLocal,即线程本地存储(TLS)对象
private static final ThreadLocal sThreadLocal = new ThreadLocal();
// Looper内的消息队列
final MessageQueue mQueue;
// 当前线程
Thread mThread;
//其他属性

// 每个Looper对象中有它的消息队列,和它所属的线程
private Looper() {
mQueue = new MessageQueue();
mRun = true;
mThread = Thread.currentThread();
}

// 我们调用该方法会在调用线程的TLS中创建Looper对象
public static final void prepare() {
if (sThreadLocal.get() != null) {
// 试图在有Looper的线程中再次创建Looper将抛出异常
throw new RuntimeException("Only one Looper may be created per thread");
}
sThreadLocal.set(new Looper());
}
public static final void loop() {
Looper me = myLooper();  //得到当前线程Looper
MessageQueue queue = me.mQueue;  //得到当前looper的MQ

// 保证拥有此Looper的线程是本地线程
Binder.clearCallingIdentity();
final long ident = Binder.clearCallingIdentity();
// 开始循环
while (true) {
Message msg = queue.next(); // 取出message
if (msg != null) {
if (msg.target == null) {
// message没有target为结束信号,退出循环
return;
}
// 日志
if (me.mLogging!= null) me.mLogging.println(
">>>>> Dispatching to " + msg.target + " "
+ msg.callback + ": " + msg.what
);
// 将Message分发给target-->Handler
msg.target.dispatchMessage(msg);
// 还是日志。。。
if (me.mLogging!= null) me.mLogging.println(
"<<<<< Finished to    " + msg.target + " "
+ msg.callback);

final long newIdent = Binder.clearCallingIdentity();
if (ident != newIdent) {
Log.wtf("Looper", "Thread identity changed from 0x"
+ Long.toHexString(ident) + " to 0x"
+ Long.toHexString(newIdent) + " while dispatching to "
+ msg.target.getClass().getName() + " "
+ msg.callback + " what=" + msg.what);
}
// 回收message资源
msg.recycle();
}
}
}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: