Как сохранить состояние при использовании AsyncTask в сервисе? - PullRequest
2 голосов
/ 06 марта 2012

Я уже некоторое время использую AsyncTask, и самая большая проблема, с которой я сталкиваюсь, заключается в том, что приложение часто падает, а рендеринг происходит слишком много раз. Например, если я установил данные для определенного макета и отобразил их, а затем повернул экран, весь макет будет снова отображен с другим GET-запросом к серверу для данных. Пока это не волновало, думая, что даже у твиттера та же проблема. Похоже, они это исправили.

Таким образом, как можно использовать AsyncTask в сервисе, а также иметь состояние экземпляра, к которому я могу обратиться, чтобы проверить, когда экран включен или даже когда приложение падает.

1 Ответ

3 голосов
/ 06 марта 2012

У меня были похожие проблемы с асинхронной операцией в действии: действие поворачивается на экране и воссоздается заново, таким образом воссоздавая асинктическую задачу.

Чтобы решить эту проблему:

  • просто, но не элегантно: предотвращение уничтожения активности с помощью android: configChanges = "direction" в вашем манифесте для вашей активности.

  • немного сложнее: создайте класс, в котором хранятся текущие элементы управления активностью, сохраните его в onRetainNonConfigurationInstance и восстановите его в onCreate. Когда запускается asynctask, вместо непосредственного общения с действием, он обращается к этому классу, который сохраняется посредством ротации. Я могу предоставить некоторый код, если вы хотите (это немного долго).

Редактировать: вот код.

        package com.ybi;

        import android.app.Activity;
        import android.os.AsyncTask;
        import android.os.Bundle;
        import android.widget.TextView;

        public class EmptyShellActivity extends Activity {

            private ActivityControl activityControl;
            private EmptyShellTask emptyShellTask;

            private TextView textView;


            @Override
            protected void onCreate(Bundle savedInstanceState) {
                super.onCreate(savedInstanceState);
                setContentView(R.layout.main);
                textView = (TextView)findViewById(R.id.textView1);
                restoreFromObject();
            }

            @Override
            public Object onRetainNonConfigurationInstance() {
                activityControl.textView = null;
                return activityControl;
            }

            private void restoreFromObject() {
                activityControl = (ActivityControl) getLastNonConfigurationInstance();
                if (activityControl == null) {
                    activityControl = new ActivityControl();
                    activityControl.textView = textView;
                    activityControl.textView.setText("Doing");
                    emptyShellTask = new EmptyShellTask();
                    emptyShellTask.execute((Void[])null);
                } else {
                    activityControl.textView = textView;
                    if (activityControl.isInProgress)
                        activityControl.textView.setText("Doing");
                    else
                        activityControl.textView.setText("Done");
                }
            }

            protected class ActivityControl {
                protected boolean isInProgress;
                protected TextView textView;
            }

            private class EmptyShellTask extends
            AsyncTask<Void, Void, Void> {

                @Override
                protected Void doInBackground(Void... params) {
                    activityControl.isInProgress = true;
                    try {
                            Thread.sleep(3000);
                    } catch (InterruptedException e) {
                        // say something
                    }
                    return null;
                }

                @Override
                protected void onPostExecute(Void result) {
                    super.onPostExecute(result);
                    activityControl.isInProgress = false;
                    activityControl.textView.setText("Done");
                }
            }
        }

Я только что удалил некоторые вещи из одного из моих классов. Я обычно использую интерфейс вместо написания кода в postExecute. Это помогает предотвратить повсеместное использование фрагментов кода (например, повторение отображения «Готово»).

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

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