1Handler 如何初始化
handler一般是使用方式是在主线程Handler handler = new Handler();初始化Handler,然后就可以愉快的使用了,此时的handler可以用于更新ui线程,在handleMessage中进行的操作相当于在ui线程。如果不是在ui线程初始化,这种初始化方式会报错。
Handler handler = new Handler(Looper.getMainLooper()); 可以更新ui。
2 Handler一定要在主线程实例化吗?
尝试在子线程中初始化handler是无法使用的,会报下面的错误:
java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
at android.os.Handler.<init>(Handler.java:200)
at android.os.Handler.<init>(Handler.java:114)
at com.example.hpuzz.myapplication.MainActivity$2.run(MainActivity.java:86)
at java.lang.Thread.run(Thread.java:761)
如果要在子线程中使用,需要手动调用Looper.prepare();
Looper.loop();
然后就可以愉快的发送消息了,但此时是不能更新ui的。
3 new Handler()和new Handler(Looper.getMainLooper())的区别
Handler handler = new Handler()不带参数的这种初始化方式,会默认用当前线程的looper,如果需要刷新UI就需要在主线程下运行。
如果在其他线程,也要更新ui的话,要Handler handler = new Handler(Looper.getMainLooper());这种最终的消息处理是在UI线程中。
在其他线程Handler handler = new Handler();之前需要Looper.prepare(); Handler handler = new Handler();Looper.loop();
或者Handler handler = new Handler(Looper.getMainLooper());
4 Handler 内存泄漏
private MyHandler mHandler;
static class MyHandler extends Handler
{
WeakReference<TaskCenterActivity> mWeakReference;
public MyHandler(TaskCenterActivity activity)
{
mWeakReference=new WeakReference<TaskCenterActivity>(activity);
}
@Override
public void handleMessage(Message msg)
{
final TaskCenterActivity activity=mWeakReference.get();
if(activity!=null && msg.what == 1)
{
if (activity.mAwardGetDialog != null){
activity.mAwardGetDialog.dismiss();
}
}
}
}
内存泄漏原因:
内部类默认持有外部类的引用,如果handler发送延迟消息,此时关闭activity,由于延迟消息,线程执行还没有结束,都会造成Activity无法销毁,从而造成内存泄漏。
Handler发送的Message会被发送的MessageQueue里面,当消息Message有延迟处理时,会留在MessageQueue里面,而Message是持有mHandler的引用,Handler又是通过匿名内部类的形式创建的,会默认持有外部类Activity的引用。既然有引用存在,垃圾回收就无法回收这个activity,所以每次打开activity然后关闭,activity就会发生泄漏,最终超出可使用内存,有造成内存溢出的危险。
-------分隔线------------
5 补充
Handler 可以直接post 里面是个Runnable,这里实际上没有创建新的线程,会在handler所在线程执行,内部直接调用run方法(不是直接开启线程),所以不要传递耗时操作。