У меня есть 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();
        }
    }
}

Любые предложения будут с благодарностью.

Спасибо!

-2
MONU KUMAR 24 Фев 2018 в 09:04

3 ответа

Лучший ответ

Никогда не пытайтесь обновить элемент пользовательского интерфейса напрямую из метода doInBackground(). Цель doInBackground() - не блокировать пользовательский интерфейс, запустив его в отдельном потоке, чтобы выгрузить часть работы из основного потока (потока пользовательского интерфейса). Поэтому вместо этого doInBackground() вызовите publishProgress(), чтобы передать ваш прогресс в функцию onProgressUpdate() для выполнения пользовательского интерфейса.

1
MoGa 24 Фев 2018 в 06:16

doInBackground() из AsyncTask предназначен для работы в фоновом режиме, и никакой другой поток не может обновить пользовательский интерфейс, кроме MainThread .

Что вы можете сделать, это сделать все вычисления в doInBackground() и вернуть его. Затем нарисуйте onPostExecute(). Или вы можете использовать обработчик MainThread для рисования из doInBackground().

Handler mainHandler = new Handler(Looper.getMainLooper());

Или

Handler mainHandler = new Handler(context.getMainLooper());
0
ADM 24 Фев 2018 в 06:21

Вы можете использовать метод onPostExecute () для внесения любых изменений в пользовательский интерфейс, поэтому вам не нужно создавать метод для этого.

0
Sagar A 24 Фев 2018 в 06:35