Управление текущими объектами View и Class‹?›

У меня есть служебный класс AppUtils для всего приложения, где я могу публиковать информацию, относящуюся к приложению, в любом случае:

  1. либо как SnackBar, когда я в приложении
  2. или с помощью диспетчера уведомлений

Например, когда сообщения идут как Snackbar, мне нужна дорожка текущего отображаемого контейнера View, чтобы использовать его в Snackbar.make(view, text, length); Когда я хочу опубликовать это сообщение с помощью NotificationManager.notify(int, Builder);, и мне нужна подпись класса в здесь

Intent resultIntent = new Intent(this, ResultActivity.class);

Поэтому у меня в AppUtils есть:

public static void setCurrentViewAndClass(View v, Class<?> c)
{
    view = v; // view is static
    cls = c;  // cls is static
}

где я могу вспомнить отовсюду в моем проекте текущий вид (для параметра Snackbar) и cls (для намерения уведомления).

Далее я очищаю эти параметры, например. когда я выхожу из приложения в фоновом режиме:

public static void clearCurrentViewAndClass()
{
    view = null;
    cls = null;
}

О. Если эти параметры НЕ нулевые, я знаю, что мое приложение имеет фокус с соответствующим представлением, и я могу отобразить соответствующее сообщение в виде снэкбара. B. Когда эти параметры равны null, я знаю, что мое приложение работает в фоновом режиме, и я хочу отобразить соответствующее сообщение в виде уведомления.

Поэтому всякий раз, когда создается или возобновляется фрагмент/активность, я вызываю setClassAndview() его в каждом onResume(), чтобы запомнить параметры.

Есть ли более элегантный способ отслеживать текущее отображаемое действие или активный класс?


person Ralf Wickum    schedule 26.10.2016    source источник


Ответы (3)


В качестве примера... создайте класс приложения (MyApp), зарегистрированный в AndroidManifest:

<application
        android:name=".MyApp"
        ...>

В классе приложения MyApp .onCreate() установите:

registerActivityLifecycleCallbacks(new MyAppActivityLifecycleCallbacks());

В MyApp создайте статическое поле, содержащее количество видимых действий и метод для определения того, находится ли приложение на переднем плане или нет:

private static int mActivityCount = 0;

public static boolean isAppInForeground() {
    return mActivityCount != 0;
}

И, наконец, настройте класс ActivityLifecycleCallbacks для учета видимых действий:

private static final class MyAppActivityLifecycleCallbacks implements ActivityLifecycleCallbacks {

        public void onActivityCreated(Activity activity, Bundle bundle) {
            // No operations
        }

        public void onActivityDestroyed(Activity activity) {
            // No operations
        }

        public void onActivityPaused(Activity activity) {
            // No operations
        }

        public void onActivityResumed(Activity activity) {
            // No operations
        }

        public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
            // No operations
        }

        public void onActivityStarted(Activity activity) {
            mActivityCount++;
        }

        public void onActivityStopped(Activity activity) {
            mActivityCount--;
        }
    }

И теперь вы должны иметь возможность вызывать MyApp.isAppInForeground(), чтобы определить, находится ли какое-либо из ваших действий в настоящее время на переднем плане. Если вам нужна ссылка на текущую видимую активность, вы также можете обработать это здесь.

person Jason Grife    schedule 01.11.2016
comment
это отлично работает для действий; очень хорошо! Есть ли что-то подобное для Фрагментов? - person Ralf Wickum; 08.11.2016
comment
Android SDK не предоставляет этого для фрагментов, но вы можете создать базовый фрагмент, из которого будут расширяться все ваши фрагменты. В этих событиях жизненного цикла базового фрагмента вы будете выполнять обратные вызовы. И ваш класс приложения может быть настроен как слушатель для этих обратных вызовов. - person Jason Grife; 12.11.2016
comment
Есть ли примеры для этих обратных вызовов жизненного цикла фрагментов с настройкой приложения в качестве прослушивателя? - person Ralf Wickum; 15.11.2016

Вы можете использовать ActivityManager для получения текущей активности.

Эта ссылка объясняет, как это сделать.

Однако вы не можете получить текущий фрагмент, поскольку одновременно может быть несколько фрагментов. Вы можете найти текущий фрагмент в определенной ViewGroup с помощью FragmentManager.

getActivity().getFragmentManager().findFragmentById(R.id.fragment_container);
person Efe Budak    schedule 26.10.2016
comment
Да, тогда я все равно должен отслеживать соответствующий идентификатор R.id.fragment_container. - person Ralf Wickum; 27.10.2016
comment
Если ответ полезен, отметьте его как правильный. - person Efe Budak; 27.10.2016
comment
Нет, это не так. Я не хочу отслеживать Контейнеры - person Ralf Wickum; 27.10.2016

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

Это работает следующим образом:

  1. Вы подписываетесь на события в каждом интересующем компоненте после его полной инициализации.
  2. Получить и обработать событие, опционально отменить событие, если компонент считает, что другим компонентам оно не нужно.
  3. Отписаться, когда компонент больше не нуждается в событиях (представление скрыто/отсоединено, фрагмент уничтожен, активность закрыта/минимизирована).

Прелесть этого подхода заключается в гибкости — вы всегда можете добавить больше логики вокруг каждого события, не затрагивая другие компоненты, которые подписываются на него. Кроме того, вы можете выбрать лучшее время для подписки/отмены подписки независимо для каждого компонента (например, уведомления могут быть отправлены в любое время, но закусочные должны отображаться только тогда, когда активность видна и возобновлена).

Есть несколько хороших вариантов реализации шины событий в вашем приложении:

  1. Глобальные трансляции Android: лучше всего подходит при наличии нескольких компонентов высокого порядка. (Деятельность, Услуги, Приемники вещания), интересующиеся общими событиями. Вы можете использовать приоритеты фильтров намерений и упорядоченные широковещательные рассылки, чтобы отменить обработку событий на полпути.
  2. LocalBroadcastManager. Очень простой, мало функций, но также простой в использовании со знакомым API.
  3. Различные специализированные библиотеки шин событий, выберите понравившуюся.
  4. Различные API, которые можно использовать как шины событий, даже если это не является их основной целью: RxJava (рекомендую прочитать этой статьи), PendingIntents, ContentResolver.notifyUri и т. д.
person user1643723    schedule 04.11.2016