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

结合源代码详解android消息模型

2015-09-03 12:14 681 查看
Handler是整个消息系统的核心,是Handler向MessageQueue发送的Message,最后Looper也是把消息通知给Handler,所以就从Handler讲起。

一、Handler

Handler的构造函数有很多,但本质差不多:

public Handler() {
this(null, false);
}


  

public Handler(Callback callback, boolean async) {
//自动绑定当前线程的looper
mLooper = Looper.myLooper();
if (mLooper == null) {
throw new RuntimeException(
"Can't create handler inside thread that has not called Looper.prepare()");//从这可以看出,创建Handler必须有Looper
}
mQueue = mLooper.mQueue;  //Looper的MessageQueue
mCallback = callback;     //一个回掉接口
mAsynchronous = async;
}


这个是创建给定Looper的Handler :

public Handler(Looper looper, Callback callback, boolean async) {
mLooper = looper;
mQueue = looper.mQueue;
mCallback = callback;
mAsynchronous = async;
}


二、Looper的源代码:

public static Looper myLooper() {
return sThreadLocal.get();
}


  在一个子线程中创建Looper的一般步骤:(这是我自己写的,不是源代码)

class MyThread extends Thread{
public Handler handler;
public Looper looper;
public void run() {
Looper.prepare();//创建一个looper
looper = Looper.myLooper();
handler = new Handler(){
@Override
public void handleMessage(Message msg) {
System.out.println("currentThread->"+Thread.currentThread());
}
};
Looper.loop();//让消息循环起来
}
}


  下面就看看Looper.prepare,Looper.loop方法:

public static void prepare() {
prepare(true);
}

private static void prepare(boolean quitAllowed) {
if (sThreadLocal.get() != null) {//sThreadLocal使得线程能够保持各自独立的一个对象。
throw new RuntimeException("Only one Looper may be created per thread");
}
sThreadLocal.set(new Looper(quitAllowed));
}


  Looper.prepare():

public static void loop() {
final Looper me = myLooper();
if (me == null) {    //如果Looper为空
throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
}
final MessageQueue queue = me.mQueue;

。。。。
for (;;) {
Message msg = queue.next(); // 循环下一个
if (msg == null) {
// No message indicates that the message queue is quitting.
return;
}

。。。。

msg.target.dispatchMessage(msg);  //分发消息,msg.target就是Handler

if (logging != null) {
logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);
}
。。。。

msg.recycle();  //回收msg到msgPool
}
}


  从这些代码可以看出Looper不断检查MessagePool是否有《==Message,有的话就通过Handler的dispatchMessage(msg)发送出去,利用Handler与外界交互。

3.Message的源代码:

public static Message obtain() {   //得到Message对象
synchronized (sPoolSync) {
if (sPool != null) {
Message m = sPool;
sPool = m.next;
m.next = null;
sPoolSize--;
return m;
}
}
return new Message();  //没有就新建
}


  handler.obtainMessage()方法:

public final Message obtainMessage()
{
return Message.obtain(this);  //通过Message的obtain方法
}


  

public static Message obtain(Handler h) {  //就是这个方法
Message m = obtain();  //最终调用的还是obtain方法
m.target = h;      //target是handler

return m;
}


  看了上边的源代码,相信你一定对Handler,message,Looper有了一定了解,对编程中常遇到的方法,知道是怎么用的啦。其实学android一定要常看源码,源码很有用。

4.下边就是上代码,实例分析:

<pre name="code" class="java">package com.example.handler_01;

import android.Manifest.permission;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Handler.Callback;
import android.os.Message;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends Activity implements OnClickListener{

private TextView textView;
private Button button;

private Handler handler = new Handler(new Callback() {//拦截消息

public boolean handleMessage(Message msg) {  //截获handler的发送的消息

Toast.makeText(getApplicationContext(), ""+1, 1).show();
//return false;
return false;//若返回true,则证明截获,下面的handleMessage就不会执行!
}
}){
public void handleMessage(Message msg) {
Toast.makeText(getApplicationContext(), ""+2, 1).show();
Person person = (Person)msg.obj;
System.out.println(person.toString());
}
};

private MyRunnable myRunnable=new MyRunnable();

private ImageView imageView;

private int images[]={R.drawable.a1,R.drawable.a2,R.drawable.a3};
private int index;

class MyRunnable implements Runnable{  //不断的更新图片,3张轮换

@Override
public void run() {
index++;
index=index%3;  //不断循环
imageView.setImageResource(images[index]);
handler.postDelayed(myRunnable, 1000);  //每隔一段时间执行myRunnable
System.out.println("MyRunnable中的线程:"+Thread.currentThread());//运行在当前主线程!
}

}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView = (TextView) findViewById(R.id.textview);
imageView = (ImageView) findViewById(R.id.imageView1);
button = (Button) findViewById(R.id.button1);
button.setOnClickListener(this);
new Thread(){
@Override
public void run() {
try {
Thread.sleep(2000);
/*Message message = new Message();
message.arg1=88;*/
Message message = handler.obtainMessage();

Person person = new Person();
person.age=20;
person.name="chaochao";
message.obj=person;
handler.sendMessage(message);//在子线程中向主线程发消息。
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

}
}.start();
handler.postDelayed(myRunnable, 1000);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.button1:
handler.removeCallbacks(myRunnable);
//handler.sendEmptyMessage(1);
break;

default:
break;
}

}

class Person{
public int age;
public String name;

public String toString() {
return "name="+name+" age="+age;
}
}
}


  布局很简单,就不上代码啦。

运行结果:



图片自己可以随便能一个。。。。

在后边再详细解析Handler的用法。。

转发请注明出处:http://www.cnblogs.com/jycboy/p/handlerjx.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: