У меня есть MapActivity
в моем приложении для Android, и я хочу нарисовать маршрут от источника до места назначения, а затем нарисовать polyline
по найденному пути. Я показываю progressDialog
, а polyline
рисуется вдоль пути.
Я думаю, что рисование полилинии - тяжелая задача, потому что она заставила progressDialog
перестать вращаться. Поэтому я поместил drawPolyline
функциональность в AsyncTask
.
Но проблема, с которой я сейчас сталкиваюсь, заключается в том, что я не получаю обновленный экран, но внезапно экран MapActivity
мигает и исчезает, и теперь я вижу MainActivity.
Почему это происходит? Я хочу знать, является ли обновление пользовательского интерфейса на фоне AsyncTask концептуально правильным? Если да, как мы можем это сделать?
Примечание. Я проверил функциональность AsyncTask, поставив точки останова. Он работает как положено, но drawPolyline вызывает ошибку. Также у drawPolyline нет проблем, так как он прекрасно работает при вызове без AsyncTask.
Вот мой код AsyncTask:
public class DrawRoute {
private WeatherMapActivity listener;
private GoogleMap mMap = WeatherMapActivity.mMap;
private List<Step> stepsInThePath = WeatherMapActivity.stepsInThePath;
public DrawRoute(WeatherMapActivity listener) {
this.listener = listener;
Log.d("imHere", "in the DrawRouteConstructor");
}
public void execute(){
Log.d("imHere", "in the execute of DrawRoute");
new DrawPolyline().execute();
}
private class DrawPolyline extends AsyncTask<Void, Void, Void> {
@Override
protected void onPreExecute() {
Log.d("imHere", "in the PreExecute");
}
@Override
protected Void doInBackground(Void... voids) {
Log.d("imHere", "in the Background");
Geocoder geocoder = new Geocoder(listener, Locale.getDefault());
mMap.addPolyline(new PolylineOptions()
.add(stepsInThePath.get(0).startLocation, stepsInThePath.get(0).endLocation)
.width(8)
.color(Color.RED));
mMap.addMarker(new MarkerOptions()
.title(MainActivity.sourceAddress)
.icon(BitmapDescriptorFactory.fromResource(R.drawable.start_red))
.position(stepsInThePath.get(0).startLocation));
mMap.addMarker(new MarkerOptions()
.title(MainActivity.destinationAddress)
.icon(BitmapDescriptorFactory.fromResource(R.drawable.end_green))
.position(stepsInThePath.get(stepsInThePath.size()-1).endLocation));
for(int i=1; i < stepsInThePath.size(); i++){
mMap.addPolyline(new PolylineOptions()
.add(stepsInThePath.get(i-1).endLocation, stepsInThePath.get(i).endLocation)
.width(8)
.color(Color.RED));
List<Address> addresses = null;
try {
addresses = geocoder.getFromLocation(stepsInThePath.get(i).startLocation.latitude, stepsInThePath.get(i).startLocation.longitude, 1);
} catch (IOException e) {
e.printStackTrace();
}
String cityName = addresses.get(0).getLocality();
if(i%5 == 0 || i == stepsInThePath.size()-1){
mMap.addMarker(new MarkerOptions()
.title(cityName)
.position(stepsInThePath.get(i).startLocation));
}
}
mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(stepsInThePath.get(0).startLocation, 5));
return null;
}
@Override
protected void onPostExecute(Void aVoid) {
Log.d("imHere", "in the PostExecute");
// progressDialog.dismiss();
}
}
}
Любые предложения будут с благодарностью.
Спасибо!
3 ответа
Никогда не пытайтесь обновить элемент пользовательского интерфейса напрямую из метода doInBackground()
. Цель doInBackground()
- не блокировать пользовательский интерфейс, запустив его в отдельном потоке, чтобы выгрузить часть работы из основного потока (потока пользовательского интерфейса). Поэтому вместо этого doInBackground()
вызовите publishProgress()
, чтобы передать ваш прогресс в функцию onProgressUpdate()
для выполнения пользовательского интерфейса.
doInBackground()
из AsyncTask
предназначен для работы в фоновом режиме, и никакой другой поток не может обновить пользовательский интерфейс, кроме MainThread .
Что вы можете сделать, это сделать все вычисления в doInBackground()
и вернуть его. Затем нарисуйте onPostExecute()
. Или вы можете использовать обработчик MainThread для рисования из doInBackground()
.
Handler mainHandler = new Handler(Looper.getMainLooper());
Или
Handler mainHandler = new Handler(context.getMainLooper());
Вы можете использовать метод onPostExecute () для внесения любых изменений в пользовательский интерфейс, поэтому вам не нужно создавать метод для этого.
Похожие вопросы
Новые вопросы
android
Android - это мобильная операционная система Google, используемая для программирования или разработки цифровых устройств (смартфоны, планшеты, автомобили, телевизоры, одежда, стекло, IoT). Для тем, связанных с Android, используйте специальные теги Android, такие как android-intent, android-activity, android-адаптер и т. Д. Для вопросов, не связанных с разработкой или программированием, но связанных с платформой Android, используйте эту ссылку: https: // android.stackexchange.com .