如何结合 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())
}
在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())
}