android – 此消息无法回收,因为它仍在使用中

我正在尝试使用 this article来创建异步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();
    }
}

但是当我运行代码时,我得到了提到的java.lang.IllegalStateException:此消息无法回收,因为它仍在使用中.当试图回收消息时.为什么这样以及如何解决它并防止内存泄漏?

解决方法

首先,让我们看看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();
}

因此,如果正在使用它,您将收到IllegalStateException

isInUse()只是检查标志,看起来像:

boolean isInUse() {
        return ((flags & FLAG_IN_USE) == FLAG_IN_USE);
    }

当我们尝试阅读该标志时,我们会看到描述:

If set message is in use.

This flag is set when the message is enqueued and remains set while it
is delivered and afterwards when it is recycled. The flag is only
cleared when a new message is created or obtained since that is the
only time that applications are allowed to modify the contents of the
message.

It is an error to attempt to enqueue or recycle a message that is
already in use.

那么我们有什么

>你不能回收消息,直到它“正在使用”
>在获得或创建新消息之前,它“正在使用中”

如何解决问题

在Message类中有一个方法recycleUnchecked()来回收消息对象,即使它正在使用中.想要你需要的东西!说明:

Recycles a Message that may be in-use.

Used internally by the MessageQueue and Looper when disposing of
queued Messages.

最糟糕的是它在内部使用并具有包访问权限.当你打电话时它在内部使用的好东西:

handler.removeMessages(int what)

所以我想最终解决方案是:

更换

msg.recycle();

try {
     msg.recycle(); //it can work in some situations
} catch (IllegalStateException e) {
     workerHandler.removeMessages(msg.what); //if recycle doesnt work we do it manually
}

相关文章

这篇“android轻量级无侵入式管理数据库自动升级组件怎么实现...
今天小编给大家分享一下Android实现自定义圆形进度条的常用方...
这篇文章主要讲解了“Android如何解决字符对齐问题”,文中的...
这篇文章主要介绍“Android岛屿数量算法怎么使用”的相关知识...
本篇内容主要讲解“Android如何开发MQTT协议的模型及通信”,...
本文小编为大家详细介绍“Android数据压缩的方法是什么”,内...