В моем пользовательском интерфейсе у меня есть ImageView
(изображение стрелки), которое необходимо обновить в режиме реального времени.Как правильно использовать AsyncTask, чтобы избежать медленного интерфейса?
Есть 2 возможные перемещения наконечника стрелы:
- вращающиеся всегда указывают на Северный
- перемещение, когда местоположение пользователя изменилось
я уже получил эти 2 метода работает должным образом.
Проблема только в том, что мой пользовательский интерфейс очень медленный и иногда застревает. Между тем, мой телефон всегда становится очень горячим, пока приложение запускается на нем. Logcat
также иногда говорит мне
Пропущенные * кадров. Приложение может делать слишком много работы над своей основной темой .
Мне сказали использовать AsyncTask
, чтобы не подчеркивать свой интерфейс. Поэтому я занимаюсь обновлением своей стрелки в AsyncTask
. Однако проблема остается. Мой пользовательский интерфейс все еще очень медленный.
Я предполагаю, что в моей реализации AsyncTask
должно быть что-то неправильно. Я вставить их здесь следующим образом:
public class ArrowheadUpdater extends AsyncTask<Float, Integer, Float> { // Float: azimuth, Integer: state
private ImageView arrowheadToRotate;
private float rotationAngle; // also in radians
// constructor
public ArrowheadUpdater(ImageView _arrowheadToRotate) {
arrowheadToRotate = _arrowheadToRotate;
rotationAngle = -1;
}
protected void onPreExecute(Float _azimuth) {
super.onPreExecute();
}
@Override
// executed first to get the angle to rotate
protected Float doInBackground(Float... arg0) {
rotationAngle = (float) (Constant.MAP_ORIENTATION_OFFSET + arg0[0]);
return rotationAngle;
}
protected void onProgressUpdated(Integer... progress) {
super.onProgressUpdate(progress);
}
protected void onPostExecute(Float result) {
super.onPostExecute(result);
\\ rotation happens here
rotateImageView(ShowPathActivity.this, arrowheadToRotate, R.drawable.marker, result);
\\ moving happens here
movaImageView(arrowhead, MapView.historyXSeries, MapView.historyYSeries);
}
Я называю AsyncTask так:
// called when sensor values change
public void onSensorChanged(SensorEvent event) { // is roughly called 350 times in 1s
//...
if (event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD) {
compassChangedTimes++;
magneticField[0] = event.values[0];
magneticField[1] = event.values[1];
magneticField[2] = event.values[2];
SensorManager.getRotationMatrix(RotationM, I, gravity, magneticField);
SensorManager.getOrientation(RotationM, direction);
if (compassChangedTimes % 50 == 0) {
// HERE!!!!!!!!!!
new ArrowheadUpdater(arrowhead).execute(direction[0]);
}
}
if (startFlag)
dataCollector.saveDataShowPath(acceleration, magneticField, startTime, currentTime);
}
Нужно ли методы 2 стрелолист-ОБНОВЛЕНИЕ в doInBackground()
вместо onPostExecute()
?
Но могут ли строки в doInBackground() обновлять пользовательский интерфейс? Я не уверен.
Есть ли что-то не так в моем AsyncTask
?
Другие догадки или комментарии приветствуются!
БОЛЬШЕ ПОДСКАЗКИ:
Я просто заметил, что, когда я просто попасть в эту деятельность, интерфейс супер медленно и застревает много. Но через некоторое время, скажем, 10 секунд, он несколько становится приемлемо гладким.
Спасибо за идею! Но в чем разница между использованием обработчика и прямым вызовом метода? Новичок, пожалуйста, помогите объяснить. –
также, возможно ли мне поставить 'SensorManager.getRotationMatrix (RotationM, I, gravity, magnetField); SensorManager.getOrientation (RotationM, direction); 'from' onSensorChanged()' в 'doInBackGround', поскольку, как вы сказали,' doInBackGround' предназначен для тяжелых вычислений? –
отправка сообщения обработчику означает, что задание будет выполнено в какой-то момент. это не значит, что это должно быть прямо сейчас, и это означает, что вы можете отправлять десятки сообщений тем временем. это дает большую гибкость планированию. В принципе, вы просто говорите: «значение имеет изменения, пожалуйста, обновите интерфейс в какой-то момент». (задержка обычно составляет всего несколько 100 миллисовских вершин, хотя) – njzk2