Сервис + AsyncTask - как действительно остановить Задачу? - PullRequest
0 голосов
/ 16 июня 2020

У меня проблемы с завершением AsyncTask, хотя ИМХО, я придерживался рекомендованной практики пометки. В приведенном ниже коде учитывается только BackButton, но лучше всего иметь общее решение для всех видов выхода из действия.

У меня есть класс MeasurementLoadingsScreen, который связывает службу следующим образом:

ServiceConnection _connection = new ServiceConnection() {
        public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
            _service = myService.Stub.asInterface(iBinder);
            runMeasurementAsyncTask();
        }

        public void onServiceDisconnected(ComponentName componentName) {
            _service = null;
        }
    };

 @Override
    protected void onStart() {
        super.onStart();
        Intent serviceIntent = new Intent();
        serviceIntent.setPackage(myService.class.getPackage().getName());
        serviceIntent.setAction(myService.class.getName() + ".ACTION_BIND");
        bindService(serviceIntent, _connection, BIND_AUTO_CREATE);
    }

 @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_measurement_loadingscreen);
        findViewsById();
        setDefaultVisibility();

        intent = getIntent();
       //myStuff
    }

Экран MeasurementLoadingScreen содержит AsyncTask с WeakReference (или SoftReference, попробовал оба).

private void runMeasurementAsyncTask() {
 //myStuff
        meTask = new MeasurementTask(this);
        meTask.execute();
    }

private static class MeasurementTask extends AsyncTask<Integer, Integer, String> {
        private WeakReference<MeasurementLoadingScreen> activityReference;
        private ServiceHelper serviceHelper;
       //myStuff
        public static boolean isRunning = false;


        MeasurementTask(MeasurementLoadingScreen context) {
            activityReference = new WeakReference<>(context);
            serviceHelper = new ServiceHelper(context._service);
        }

        @Override
        protected String doInBackground(Integer... params) {
            MeasurementLoadingScreen activityReference = this.activityReference.get();
            isRunning = true;
            //myStuff, it's ok to finish running this before cancelling
            if (isCancelled()) {
                return "cancelled";
            }
            // more myStuff
            if (isCancelled()) {
                return "cancelled";
            }

           [...]

 @Override
        protected void onCancelled(){
          //myStuff: safely shutdown measurement process, might take a few seconds at worst
            meTask.isRunning = false;

            if(activityReference.get() != null) {
                activityReference.get().finish();  //it does not work without this, either
            }
          super.onCancelled();
        }

Когда я возвращаюсь дважды (независимо от поведения c), он должен (безопасно) прерваться AsyncTask:

  @Override
    public void onBackPressed()
    {
        if (mBackPressed + TIME_INTERVAL > System.currentTimeMillis())
        {
            if (meTask == null) {
                super.onBackPressed();
                return;
            }
            cancelTask();
            Toast.makeText(getBaseContext(), "Cancelling Task", Toast.LENGTH_SHORT).show();
            return;
        }
        else { Toast.makeText(getBaseContext(), "Tap back button in order to exit", Toast.LENGTH_SHORT).show(); }

        mBackPressed = System.currentTimeMillis();
    }
    @Override
    protected void onStop() {
        super.onStop();
        if (_connection != null)
        unbindService(_connection);
        finish();//
    }

    @Override
    public void onPause() {
        int i = 0;
        super.onPause();
//poll state of task here
        finish();
    }

Кажется, мне не удается остановить выполнение задачи. Если я установил meTask = null; в onPause, например, он в конечном итоге будет go через onCancelled, а затем вызовет onStop, также завершив службу. Но нет никакого способа дождаться, пока onCancelled сделает свое дело и уведомит меня с помощью isRunningflag, getStatus или чего-то еще. Приложение просто зависает, однако я опрашиваю задачу, которая все время остается ВЫПОЛНЕННОЙ, если я не установил для нее значение null (конечно, нежелательно).

Изменить: я добавил попытку опроса, которая позволяет вызывать действие onPause / onStop в конечном итоге, но моя основная проблема связана с опросом, я никогда не вижу завершенную / завершающую задачу, хотя onCancelled вызывается в какой-то момент, но только после того, как я установил meTask = null;, он не продолжает отмену

public void onBackPressed() {
        int i=0;
        if (mBackPressed + TIME_INTERVAL > System.currentTimeMillis())
        {
            if (meTask == null) {
                super.onBackPressed();
                return;
            }
            cancelTask();
            Toast.makeText(getBaseContext(), "Cancelling Task", Toast.LENGTH_SHORT).show();
            while ((meTask.getStatus()== AsyncTask.Status.RUNNING) && (i < 20000)) {
//waiting etc., checking für isRunning doesn't work either
                i++;
            }
            Log.d(TAG, "meTask  " + meTask.getStatus());
            meTask = null;
            Log.d(TAG, "meTask null after " + i);
            super.onBackPressed();
            return;

Edit 2:
Content of cancelTask()
private void cancelTask() {
        if (meTask != null) {
            Log.d(TAG, "Async Task Cancel... ");
            meTask.cancel(true);
        }
    }

Редактировать 3: Независимо от того, где я поставил отмену (true), например onPause, onStop, задача остается активной и дает мне только вывод журнала

    if (isCancelled()) {
            Log.d(TAG, "Cancel after XYZ");
            return "cancelled";
    }

и

@Override
        protected void onCancelled() {
            super.onCancelled();
            isRunning = false;
            Log.d(TAG, "...Async Task Cancelled ");
        }

в самом конце, после завершения onPause, onStop, onDestroy. Я в своем уме. Неудивительно, что Задача продолжает работать некоторое время, но она должна остановиться до того, как служба освободится. Как дождаться завершения задачи sh?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...