使用Handlerf发送消息或使用Handler轮询时,报错IllegalStateException:This message is already in use.;

时间:2022-01-12 04:51:35
 java.lang.IllegalStateException: { when=-107ms what=9 obj=com.saicmaxus.maxuslife.model.CarInfo@be47330 target=com.cc.fragment.OwnerServiceFragment$13 } This message is already in use.

很明显,它的意思是这个消息正在使用中,不可以使用;

                Message msgCarcarstatus = new Message();
msgCarcarstatus.obj = carInfo;
msgCarcarstatus.what = CARCARSTATUSUPDATAWHAT;
mHandler.sendMessageDelayed(msgCarcarstatus,1000*15);
// mHandler.sendMessageDelayed(msg,1000*15); //IllegalStateException:This message is already in use.

上面代码所示,我们再从新new Message传过去就可以了;

如果感觉这样每次都new效果不过不好,还可以这样使用,Message message = YourHandler.obtainMessage();不会重复创建Message,节省内存开销;

                Message msgCarcarstatus = mHandler.obtainMessage();
msgCarcarstatus.obj = carInfo;
msgCarcarstatus.what = CARCARSTATUSUPDATAWHAT;
mHandler.sendMessageDelayed(msgCarcarstatus,1000*15);
// mHandler.sendMessageDelayed(msg,1000*15); //IllegalStateException:This message is already in use.

看完整代码:

   private Handler mHandler = new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
if(msg.what == CARCARSTATUSUPDATAWHAT){
CarInfo carInfo = (CarInfo) msg.obj;
showCarCarstatus(carInfo.get1(),carInfo.get2(),true);
//轮询
Message msgCarcarstatus = mHandler.obtainMessage();
msgCarcarstatus.obj = carInfo;
msgCarcarstatus.what = CARCARSTATUSUPDATAWHAT;
mHandler.sendMessageDelayed(msgCarcarstatus,1000*15);
// mHandler.sendMessageDelayed(msg,1000*15); //IllegalStateException:This message is already in use.
}
}
};

//发送消息

private final int CARCARSTATUSUPDATAWHAT = 9;

//定时刷新
Message msg = new Message();
msg.obj = ownerList.get(position);
msg.what = CARCARSTATUSUPDATAWHAT;
mHandler.sendMessageDelayed(msg,1000*15);

移除标记是what的消息:mHandler.removeMessages(CARCARSTATUSUPDATAWHAT);

移除全部的消息:mHandler.removeCallbacksAndMessages(null);

附源码:

/**
* Returns a new {@link android.os.Message Message} from the global message pool. More efficient than
* creating and allocating new instances. The retrieved message has its handler set to this instance (Message.target == this).
* If you don't want that facility, just call Message.obtain() instead.
*/
public final Message obtainMessage()
{
return Message.obtain(this);
}
/**
* Same as {@link #obtain()}, but sets the value for the <em>target</em> member on the Message returned.
* @param h Handler to assign to the returned Message object's <em>target</em> member.
* @return A Message object from the global pool.
*/
public static Message obtain(Handler h) {
Message m = obtain();
m.target = h; return m;
}
/**
* Return a new Message instance from the global pool. Allows us to
* avoid allocating new objects in many cases.
*/
public static Message obtain() {
synchronized (sPoolSync) {
if (sPool != null) {
Message m = sPool;
sPool = m.next;
m.next = null;
m.flags = 0; // clear in-use flag
sPoolSize--;
return m;
}
}
return new Message();
}

注释说:从全局池返回一个新的Message实例。允许我们避免在很多情况下分配新对象

大概意思就是:如果MessagePool中存在Message,就把这个Message中的内容清空后返回;如果MessagePool中不存在message,就新建一个Message;所以,不管怎样我们拿到的Message都是一个全新的,都需要重新去赋值;