关于handler的具体概念,我在前面的线程间的通信已经讲过了,这里就不多说,这里主要是讲一下静态handler的使用,因为,如果我们在每个activity或是其他类里面都new 一个handler其实是比较低效率的做法,完全可以只用一个全局的静态handler来进行线程和主线程的通信。
先看测试代码:
package com.mnsn.lldr.utils;
import java.util.ArrayList;
import java.util.List;
import android.os.Handler;
public class MyHandlerUtil {
private static MyHandlerUtil instance;
private static List<IHandler> task = new ArrayList<MyHandlerUtil.IHandler>();
private Handler handler = new Handler() {
public void handleMessage(android.os.Message msg) {
for (int i = 0; i < task.size(); i++) {
task.get(i).refeshData(msg);
task.remove(i);
i--;
}
};
};
public static synchronized MyHandlerUtil getInstance(IHandler iHandler) {
if(instance == null){
instance = new MyHandlerUtil();
}
if (!task.contains(iHandler)) {
task.add(iHandler);
}
return instance;
}
public Handler getHandler() {
return handler;
}
public interface IHandler {
void refeshData(android.os.Message msg);
}
}
package com.mnsn.lldr.utils;
import com.mnsn.lldr.R;
import android.app.Activity;
import android.os.Bundle;
import android.os.Message;
import android.widget.TextView;
public class MyHanlderTextActivity extends Activity implements MyHandlerUtil.IHandler{
private MyHandlerUtil handlerUtil;
private TextView tv;
private boolean isDestoryed;
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
handlerUtil = MyHandlerUtil.getInstance(this);
tv = (TextView) findViewById(R.id.tv);
new Thread(){
public void run() {
getHttp();
handlerUtil.getHandler().sendEmptyMessage(1);
};
}.start();
}
private void getHttp(){
}
@Override
protected void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
isDestoryed = true;
}
@Override
public void refeshData(Message msg) {
if(isDestoryed||tv==null){
return;
}
if(msg.what==1){
tv.setText("刷新数据成功");
}
}
}
这里有个值得注意的是,在刷新数据的时候要判断一下activity是否已经被销毁,如果销毁了,则不必再更新数据。另外,网路上有很多人说这里的handler会造成内存泄露,所以使用虚引用或者软引用,类似我之前的博客里写道的,其实之所以会造成内存泄露是因为这里的非静态内部类持有activity的引用,主要是Thread的生命周期如果过长造成的,网路上只是在handler的构造方法里使用activity的虚/软引用,这其实是没什么效果的,因为handler里面处理消息时,已经是在主线程中,所以不会执行耗时操作,也就不存在内存泄露了。
另外一点,因为我这里只考虑了线程向主线程发消息,也就是说消息处理是在主线程中进行的,所以task用的arrylist,是非线程安全的,如果要扩展到主线程向子线程中发消息,则要使用线程安全的list。
可以改为:
private static List task =Collections.synchronizedList(new ArrayList());