Pit*_*tel 6 android android-handler
我正在尝试使用这篇文章来创建异步UDP套接字.
所以我有这个代码:
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Message;
import java.net.DatagramSocket;
import java.net.SocketException;
public class UdpThread
extends HandlerThread {
private static final String TAG = "UDP";
private final Handler uiHandler, workerHandler;
private final DatagramSocket socket = new DatagramSocket();
public UdpThread(final Handler uiHandler, final String hostname, final int port) throws SocketException {
super(TAG);
this.uiHandler = uiHandler;
start();
workerHandler = new Handler(getLooper(), new Handler.Callback() {
@Override
public boolean handleMessage(final Message msg) {
/*
if (msg.what == port && msg.obj == hostname) {
final InetSocketAddress address = new InetSocketAddress(hostname, port);
Log.d(TAG, "Connecting to " + address);
try {
socket.connect(address);
} catch (SocketException se) {
throw new RuntimeException(se);
}
}
*/
msg.recycle(); //java.lang.IllegalStateException: This message cannot be recycled because it is still in use.
return true;
}
});
workerHandler.obtainMessage(port, hostname).sendToTarget();
}
}
Run Code Online (Sandbox Code Playgroud)
但是当我运行代码时,我java.lang.IllegalStateException: This message cannot be recycled because it is still in use.在尝试回收消息时得到了提及的信息.为什么这样以及如何解决它并防止内存泄漏?
首先,让我们看看Message recycle()方法是如何工作的.
public void recycle() {
if (isInUse()) {
if (gCheckRecycle) {
throw new IllegalStateException("This message cannot be recycled because it "
+ "is still in use.");
}
return;
}
recycleUnchecked();
}
Run Code Online (Sandbox Code Playgroud)
所以IllegalStateException如果它正在使用你就会得到
isInUse() 只是检查标志,看起来像:
boolean isInUse() {
return ((flags & FLAG_IN_USE) == FLAG_IN_USE);
}
Run Code Online (Sandbox Code Playgroud)
当我们尝试阅读该标志时,我们会看到描述:
如果设置消息正在使用中.
当邮件入队时设置此标志,并在邮件传送时保持设置,之后再循环.只有在创建或获取新消息时才会清除该标志,因为这是允许应用程序修改消息内容的唯一时间.
尝试排队或回收已在使用的邮件是错误的.
那么我们有什么
如何解决问题
recycleUnchecked()Message类中有一个方法可以回收消息对象,即使它正在使用中.这就是你需要的东西!说明:
重新循环可能正在使用的消息.
在处理排队的消息时,由MessageQueue和Looper在内部使用.
最糟糕的是它在内部使用并具有包访问权限.当你打电话时它在内部使用的好东西:
handler.removeMessages(int what)
Run Code Online (Sandbox Code Playgroud)
所以我想最终解决方案是:
更换
msg.recycle();
Run Code Online (Sandbox Code Playgroud)
至
try {
msg.recycle(); //it can work in some situations
} catch (IllegalStateException e) {
workerHandler.removeMessages(msg.what); //if recycle doesnt work we do it manually
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1166 次 |
| 最近记录: |