Android: можно ли делать действительно быстрые и плавные обновления пользовательского интерфейса на основе входящих сообщений MQTT
Я установил действительно простое тестовое приложение. Это только текстовое представление, которое обновляется каждый раз, когда приходит новое сообщение от моего брокера mqtt, на который я подписываюсь из своего приложения. Он работает нормально, если я публикую сообщения брокеру каждую секунду, а также каждые 0,5 секунды. Если я опубликую для брокера быстрее, чем это произойдет, в пользовательском интерфейсе моего тестового приложения для Android возникнут проблемы с отрисовкой. Он не падает, но время от времени зависает с крошечными всплесками задержки. Часто, когда это происходит, я получаю это сообщение в моем журнале. "I/ViewRootImpl: jank_removeInvalidNode, все узлы в списке jank вышли из строя". Если я скрою пользовательский интерфейс, я смогу увидеть в журнале, что каждое сообщение доставляется плавно и без проблем, но как только я задействую любую графику, оно не может идеально соответствовать.Причина, по которой я тестирую это, заключается в том, что в дальнейшем я хочу делать анимацию на основе сообщений mqtt, которые будут в значительной степени в реальном времени. Возможно ли вообще этого достичь? Я новичок как в разработке Android, так и в mqtt. Код из моего тестового проекта ниже.
public class MQTTHelper {
public MqttAndroidClient mqttAndroidClient;
String serverUri;
String subscriptionTopic;
String username;
String password;
public MQTTHelper(Context context, String serverUri, String clientId, String subscriptionTopic, String username, String password) {
this.serverUri = serverUri;
this.subscriptionTopic = subscriptionTopic;
this.username = username;
this.password = password;
mqttAndroidClient = new MqttAndroidClient(context,serverUri, clientId);
mqttAndroidClient.setCallback(new MqttCallbackExtended() {
@Override
public void connectComplete(boolean reconnect, String serverURI) {
Log.d("connect", "connectComplete: " + serverURI);
}
@Override
public void connectionLost(Throwable cause) {
Log.d("connectionLost", "connectionLost: " + "Lost connection");
}
@Override
public void messageArrived(String topic, MqttMessage message) throws Exception {
}
@Override
public void deliveryComplete(IMqttDeliveryToken token) {
}
});
connect();
}
public void setCallback(MqttCallbackExtended callback) {
mqttAndroidClient.setCallback(callback);
}
private void connect() {
MqttConnectOptions connectOptions = new MqttConnectOptions();
connectOptions.setAutomaticReconnect(true);
connectOptions.setCleanSession(false);
connectOptions.setUserName(username);
connectOptions.setPassword(password.toCharArray());
try {
mqttAndroidClient.connect(connectOptions, null, new IMqttActionListener() {
@Override
public void onSuccess(IMqttToken asyncActionToken) {
DisconnectedBufferOptions disconnectedBufferOptions = new DisconnectedBufferOptions();
disconnectedBufferOptions.setBufferEnabled(true);
disconnectedBufferOptions.setPersistBuffer(false);
disconnectedBufferOptions.setDeleteOldestMessages(false);
mqttAndroidClient.setBufferOpts(disconnectedBufferOptions);
subscribeToTopic();
}
@Override
public void onFailure(IMqttToken asyncActionToken, Throwable exception) {
Log.d("onFailure", "Failed to connect to: " + serverUri + exception.toString());
}
});
} catch (MqttException e) {
e.printStackTrace();
}
}
private void subscribeToTopic() {
try {
mqttAndroidClient.subscribe(subscriptionTopic, 0, null, new IMqttActionListener() {
@Override
public void onSuccess(IMqttToken asyncActionToken) {
Log.d("subscribe", "onSuccess: " + "subscribed");
}
@Override
public void onFailure(IMqttToken asyncActionToken, Throwable exception) {
Log.d("subscribe", "onFailure: " + "subscription failed!");
}
});
} catch (MqttException e) {
System.err.println("Not able to subscribe");
e.printStackTrace();
}
}
}
открытый класс MainActivity расширяет AppCompatActivity {
private MQTTHelper mqttHelper;
private TextView textView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView = findViewById(R.id.textView);
connectToMQTTBroker();
}
private void connectToMQTTBroker() {
mqttHelper = new MQTTHelper(getApplicationContext(), SERVER_URI, CLIENT_ID, SUBSCRIPTION_TOPIC, USERNAME, PASSWORD);
mqttHelper.setCallback(new MqttCallbackExtended() {
@Override
public void connectComplete(boolean reconnect, String serverURI) {
}
@Override
public void connectionLost(Throwable cause) {
}
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
@Override
public void messageArrived(String topic, MqttMessage message) throws Exception {
Log.d("messageArrived", "messageArrived: " + message.toString());
String messageStr = message.toString();
textView.setText(messageStr);
}
@Override
public void deliveryComplete(IMqttDeliveryToken token) {
}
});
}
}