线程间通信的消息机制的Message和Handler

Message是消息机制的信息载体,开发人员可以在Message对象中封装数据,封装数据的方式有:

1)setData(),在Message中封装Bundle类型的数据,在接收方使用getData()获取该Bundle对象。

2)arg1属性,int类型,用于封装int类型变量

3)arg2属性,int类型,与arg1相似

4)what属性,int类型,用于封装int类型变量,表示消息的标识符

5)obj属性,object类型,用于封装任意类型的数据

Handler消息的发送者和处理者,常用方法有

1)public final boolean sendMessage(Message msg);

2)public void HandleMessage(Message msg);

使用消息机制发送处理消息,

public class MainActivity extends Activity {
private ImageView ivImage;
private Button btnLoadImage;
private Handler handler;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ivImage=(ImageView) findViewById(R.id.imageView1);
                handler=new InnerHandler();

}
/**
* 自定义Handler
* @author Administrator
*/
public class InnerHandler extends Handler{
@Override
public void handleMessage(Message msg) {
//接收消息
Bitmap bm=(Bitmap) msg.obj;
ivImage.setImageBitmap(bm);
}
}
/**
* 点击按钮,加载图片
* @param v
*/
public void doLoadImage(View v){
new Thread(){
public void run() {
//从网络中加载图片,即耗时操作
Bitmap bm=loadImageFromNetwork();
//创建消息
Message msg=new Message();
msg.obj=bm;
//发送消息
handler.sendMessage(msg);
};
}.start();
}
/**
* 模拟从网络中加载图片
*/
public Bitmap loadImageFromNetwork(){
Bitmap bm=null;
//模拟网络延迟8秒
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return bm=BitmapFactory.decodeResource(getResources(), R.drawable.meituan);
}


Message存在公有的无参的构造方法,所以可以用new Message()创建Message对象,但是这种做法并不推荐。因为很多时候,需要很频繁的发送消息,很频繁的创建对象,会导致较大的系统开销。为了避免较多的Message对象创建和销毁造成较大的系统开销,系统使用Message Pool(消息池)来控制和管理Message对象。

Message Pool的大小为10,即可存放10个Message对象,当需要Message对象时,直接从池中获取即可,无需创建。获取Message对象的方法:

1)Message类的obtain静态方法;

2)Handler的obtainMessage方法;

两个方法都是重载很多次,我们可以查询文档,使用方法。

在使用Message时一般遵循以下规则:

1)尽量使用Message的obtain方法或Handler的obtainMessage方法获取Message对象,而不使用构造方法创建对象。

2)严格区分Message对象的arg1,arg2,what属性。what标识消息类型,常使用常量表现其意义,而arg1,arg2则表示具体数字意义的数据。

3)可以根据具体情况,将需要封装的数据设置为全局变量,在子线程中可以直接更新,在主线程中直接获取,而无需封装。

4)尽量不要在Message中封装大量的数据,能使用obj属性封装的,就不要使用setData()/getData方法,因为其效率更高。

根据以上内容,部分代码可以更改为

public class MainActivity extends Activity {
private ImageView ivImage;
private Button btnLoadImage;
private Handler handler;
private Bitmap bm;
        protected static final int LOAD_IMAGE_COMPLETED = 0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ivImage=(ImageView) findViewById(R.id.imageView1);
handler=new InnerHandler();
}
/**
* 自定义Handler
* @author Administrator
*/
public class InnerHandler extends Handler{
@Override
public void handleMessage(Message msg) {
if(msg.what==LOAD_IMAGE_COMPLETED){
ivImage.setImageBitmap(bm);
}
}
}
/**
* 点击按钮,加载图片
* @param v
*/
public void doLoadImage(View v){
new Thread(){
public void run() {
//从网络中加载图片,即耗时操作
bm=loadImageFromNetwork();
Message msg=new Message();
·msg.what=LOAD_IMAGE_COMPLETED;
handler.sendMessage(msg);
};
}.start();
   }
}


以上代码是定义Handler的子类,并重写handleMessage方法以处理消息。其实关于Handler处理消息,我们也可以自定义类实现Handler.Callback接口,并将该接口的实现类对象作为new Handler(Callback callback)的参数以创建Handler对象

以上代码部分可以修改为:

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ivImage=(ImageView) findViewById(R.id.imageView1);
//handler=new InnerHandler();
handler=new Handler(new InnerCallback());
}
public class InnerCallback implements Handler.Callback{
@Override
public boolean handleMessage(Message msg) {
if(msg.what==LOAD_IMAGE_COMPLETED){
ivImage.setImageBitmap(bm);
}
return false;
}
}


猜你喜欢

转载自blog.csdn.net/luckgrilwyy/article/details/50404894