MVC в Android: приложение или служба для асинхронных обновлений? - PullRequest
6 голосов
/ 03 июля 2010

(прошу прощения за то, что не так ясно в моем первом посте)

Вот ситуация: у меня есть данные, которые нужно обновить из Интернета. Давайте назовем это Model.

Что я хочу сделать: По сути, это звучит как модель MVC, где Model также сохраняется в локальном (частном) хранилище. Model и связанные с ним методы являются прикладными. Есть несколько Activity, которые отображают и манипулируют различными его аспектами:

  • Пользователь перемещается по различным Activity этот дисплей Model с разных точек зрения. В настоящее время у меня есть ListActivity для всех элементов и Activity для деталей одного элемента
  • Иногда Model нуждается в обновлении. Конечно, это сделано в другом потоке. Обновление может быть вызвано несколькими Activity.
  • Есть несколько (отнимающих много времени) общих задачи, которые можно запускать из разных Activity
  • Мое приложение загружается и сохраняется Model в частное хранилище при запуске и останавливается

Моя проблема: Я не уверен, куда поместить Model и связанные задачи. Кроме того, я не знаю, какой механизм использовать для уведомления Activity. В настоящее время я придумываю 2 подхода:

  • Используйте Service и отправляйте трансляции. Сохранение на диск выполняется в Service#onDestroyed(), поэтому я хочу минимизировать это, привязав его к Activity. На данный момент я также не уверен, как доставить обновленную информацию: предоставлять ли getter в Binder или включить это в широковещательное сообщение.
  • Настройте объект Application, чтобы методы обновления и getter были доступны глобально. Затем я выполняю обновление с Activity, используя AsyncTask. Если есть другие Activity, которые находятся позади текущего Activity, они обновятся в onResume(), когда пользователь вернется назад.

Причины, по которым я не использую класс со статическими методами:

  • Мне нужно сохранить и сохранить Model на диск.
  • Некоторым методам нужен контекст для отображения тостов, уведомлений, кэширования и т. д.

Кроме того, я не помещаю эти функции в Activity, потому что есть несколько действий, которые управляют одним и тем же фрагментом постоянных данных.

Ниже приведен псевдокод, иллюстрирующий, что я имею в виду:

Использование службы:

/** Service maintaining state and performing background tasks */
class MyService extends Service {
    Model mModel;
    Binder mBinder;

    onCreate() {
        super.onCreate();
        mBinder = new Binder();
        // load mModel from disk, or do default initialization
    }

    onDestroy() {
        super.onDestroy();
        // save mModel to disk
    }

    onBind() {
        return mBinder;
    }

    class Binder {
        refresh() {
            new AsyncTask() {
                doInBackground() {
                    // update mModel from Internet
                }
                onPostExecute() {
                    sendBroadcasts(new Intent("my.package.REFRESHED"));
                }
            }.execute();
        }

        getState() {
            return mModel.getState();
        }
    }
}

/** Activity displaying result */
class MyActivity extends ListActivity {
    MyService.Binder mBinder;

    onCreate() {
        super.onCreate();
        // register mReceiver
        // bind service
    }

    onDestroy() {
        super.onDestroy();
        // unbind service
        // unregister mReceiver
    }

    /** Invokes time-consuming update */
    refresh() {
        // binding is asynchronous, and user may trigger refreshing too early
        if (mBinder != null) {
            mBinder.refresh();
        }
    }

    BroadcastReceiver mReceiver = new BroadcastReceiver() {
        onReceive(Intent intent) {
            if ("my.package.REFRESHED".equals(intent.getAction())
                    && mBinder != null) {
                updateViews(mBinder.getState());
            }
        }
    };
}

Обеспечение общего доступа к функциональности в пользовательском объекте приложения

/** Custom Application providing domain specific functionalities */
class MyApplication extends Application {
    Model mModel;

    onCreate() {
        super.onCreate();
        // load mModel from disk, or do default initialization
    }

    onTerminate() {
        super.onTerminate();
        // save mModel to disk
    }

    void refresh() {
        /** time-consuming */
    }

    getState() {
        return mModel.getState();
    }
}

/** Activity displaying result */
class MyActivity extends ListActivity {
    onResume() {
        super.onResume();

        // in case some top Activities have refreshed
        // and user is navigating back
        updateViews(((MyApplication)getApplicationContext()).getState());
    }

    /** Invokes time-consuming update */
    refresh() {
        new AsyncTask() {
            doInBackground() {
                ((MyApplication)getApplicationContext()).refresh();
            }
            onPostExecute() {
                // update the ListView according to result
                updateViews(((MyApplication)getApplicationContext()).getState());
            }
        }.execute();
    }
}

Слабые стороны, которые я могу придумать для подхода Service, - это сложность, поскольку привязка асинхронна. И очень вероятно, что мне придется повторить некоторый код, потому что у меня есть и ListActivity и Activity

Для подхода Application в документации сказано, что не следует полагаться на onTerminate() вызываемого.

Я знаю, что я очень неловкий. Как обычно решить эту проблему?

Большое спасибо.

Ответы [ 3 ]

1 голос
/ 03 июля 2010

Service s в основном подходят для чего-то, что не привязано к одному Activity (и обычно работают вместе с NotificationManager или Widget).Похоже, это не так.
Поэтому я предлагаю иметь хорошо спроектированный AsyncTask, который управляет состоянием через SharedPreferences / SQLite сам (вместо злоупотребления Applicaion) и будет запущенот ListActivity.

0 голосов
/ 03 июля 2010

Вы не объяснили, какую информацию вы получаете, но эта строка важна:

Эти задачи включают состояния, которые нуждаются быть загруженным и сохраненным изящно, когда приложение запускается и останавливается

Если это так, почему бы вам не сделать AsynTask внутри Activity?

У вас были те же проблемы с отправкой Intents с ArrayList внутри, но у меня есть приложение, которое делает именно это, и у меня нет проблем с производительностью.

0 голосов
/ 03 июля 2010

Что ж, вы могли бы расширить BroadcastReceiver вместо Сервиса, и когда он сделал то, что ему нужно, он загрузил Activity с результатами.

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