如何结合 MqttClient 和 AsyncTask?

How do combine MqttClient and AsyncTask?

在AsnyTask中使用MqttClient时,客户端回调MqttListener.messageArrived()在Async.onPostExecute()之后执行。

这意味着回复变量将在传递给侦听器回调后设置。

如果从 MqttClient 线程(从 messageArrived())调用 onTaskCompleted,则会从​​ onTaskCompleted 内部抛出异常:

MqttException (0) - android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.

public class MqttRequestHandler extends AsyncTask<Object, Void, String> implements MqttCallback {
    private OnTaskCompleted listener;
    String reply = "";

    public MqttRequestHandler(OnTaskCompleted listener) {
        this.listener = listener;
    }

    @Override
    protected String doInBackground(Object... params) {
        try {
            MqttClient client = new MqttClient("tcp://192.168.1.101", "test-client", new MemoryPersistence());
            client.setCallback(this);
            client.connect();
            client.subscribe(setup.topic);
        } catch (Exception e) {
            Log.e("MqttResponseHandler", e.toString());
        }

        return ""; //dummy, since we have to use the callback
    }

    @Override
    public void connectionLost(Throwable cause) {
        Log.d("MqttRequestHandler", "connectionLost: " + cause.toString());
    }

    @Override
    public void messageArrived(String topic, MqttMessage message) {
        this.reply = message.toString(); // not empty
    }

    @Override
    public void deliveryComplete(IMqttDeliveryToken token) {
    }

    protected void onPostExecute(String dummy) {
        listener.onTaskCompleted(this.reply); // empty string!
    }
}

listener.onTaskCompleted(..) 在执行 ImageView.setImageBitmap() 时挂起。 在 connectionLost() 中收到错误消息。

您不能从另一个线程更改视图,您必须确保从创建它的线程访问视图,这应该是 UI 线程。可以参考这个Post

How do we use runOnUiThread in Android?

在您的 listener.onTaskCompleted(..) 函数中,您应该确保从 UI 线程访问您的视图。

如果您只想使用收到的字符串,您可以删除 OnPost 执行并在 messagearrived 回调中执行 onTaskcompleted。

删除

protected void onPostExecute(String dummy) {
    listener.onTaskCompleted(this.reply); // empty string!
}

和改变

@Override
public void messageArrived(String topic, MqttMessage message) {
    this.reply = message.toString(); // not empty
}

@Override
public void messageArrived(String topic, MqttMessage message) {
    listener.onTaskCompleted(message.toString())
}