Обновление заданий стека после изменения ночного режима - PullRequest
0 голосов
/ 28 февраля 2019

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

Скажите, что у меня есть обратный стек A> B> C .Активность C позволяет изменить ночной режим, позвонив по номеру AppCompatDelegate.setDefaultNightMode().После этого вызова текущая активность (C) может обновить свою тему с помощью delegate.applyDayNight() или recreate().

Однако, когда пользователь возвращается к B или A, действия все еще используют «старый».режим, либо днем, либо ночью.

Я пытался добавить что-то подобное в Деятельности:

override fun onResume() {
  super.onResume()
  delegate.applyDayNight()
}

Но, похоже, это не работает.

Я сделал несколько попыток исправить это:

Одной из идей было бы воссоздать backstack полностью, как предлагалось здесь или здесь , но так какbackstack не статичен, для меня это не выполнимо.

Другая идея состоит в том, чтобы иметь класс, который обрабатывает изменение ночного режима и предоставляет LiveData.Каждое действие будет прослушивать LiveData для изменения режима и вызывать recreate().Тем не менее, мы застряли в бесконечном цикле, потому что Activity будет воссоздавать сразу после начала прослушивания LiveData.

Мне трудно поверить, что я первый, кто пытается обновить Activity из backstack послесмена ночного режима.Что я пропустил?

Спасибо!

Ответы [ 3 ]

0 голосов
/ 11 марта 2019

Если вы можете определить, когда изменился дневной / ночной режим, вы можете просто воссоздать занятие, которое возобновляется при извлечении заднего стека.

В следующей демонстрации есть три действия: A,B и C. A создает B, а B создает C. Активность C может изменить дневной / ночной режим.Когда C выталкивается, действие B видит изменение в дневном / ночном режиме и вызывает reCreate(), чтобы восстановить действие.То же самое происходит в действии A, когда действие B прерывается.

На видео ниже показан эффект.Светлый фон - это «дневной» режим, а темный - «ночной».

Я создал проект GitHub для этого демонстрационного приложения.Если это работает как решение, я могу включить больше текста в ответ от проекта.

enter image description here

0 голосов
/ 11 марта 2019

Полное обновление вашего заднего стека, вероятно, является излишним и может добавить некоторые издержки / отставание к UX;и, как вы упомянули, большинство приложений не будет иметь доступа к полному статическому бэк-стеку.

По сути, вы описываете более общую проблему: глобальные изменения темы или самого WindowManager влияют на последующее рисование представлений.Но предыдущие макеты для действий в стеке не могут быть перерисованы.Это может показаться странным для вас в этой ситуации, но также может быть много веских причин, по которым вы не захотите перерисовывать активность в стеке, если пользователь вернется к ней.И поэтому это не автоматическая функция.

Я могу вспомнить пару вариантов:

1) Написать собственный класс, унаследованный от Activity, который делает недействительными все его представления, когда он снова перемещается в начало стека.Например, в onResume() или onRestart(), позвоните (если в Fragment)

View view = getActivity().findViewById(R.id.viewid);
view.invalidate();

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

2) Используйте ActivityLifecycleCallbacks.Это помогает хранить всю логику в одном месте и избавляет от необходимости настраиваемого наследования, как указано выше.Вы можете сделать недействительными свои взгляды, если действия будут приостановлены / возобновлены.Вы можете включить прослушиватель, если ваше приложение меняет тему, и записать, например, SharedPreference.

Чтобы использовать, добавьте обратные вызовы в класс приложения:

registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() {

    @Override
    public void
    onActivityCreated(Activity activity, Bundle savedInstanceState) {
        //can check type of Activity for custom behaviour, if using inheritance
        if(activity instanceof MainActivity) {
           mMainActivities.put(activity, new MainActivityEntry((MainActivity)activity));
            //...
        }
    }

    @Override
    public void
    onActivityDestroyed(Activity activity) {

    } 

    @Override
    public void
    onActivityPaused(Activity activity) {
    }

    @Override
    public void
    onActivityResumed(Activity activity) {
        if(activity instanceof MainActivity) {
        //...
        }
        //can update Entry properties too
        final MainActivityEntry activityEntry = mMainActivities.get(activity);

        if(activityEntry != null) {
        //record state /perform action
        }
    }

    @Override
    public void
    onActivitySaveInstanceState(Activity activity, Bundle outState) {


    }

    @Override
    public void
    onActivityStarted(Activity activity) {


    }

    @Override
    public void
    onActivityStopped(Activity activity) {
    }
});
0 голосов
/ 07 марта 2019

создайте статическую логическую переменную в проекте, и в каждом действии проверяйте, является ли логическое значение true или false, затем применяйте дневной и ночной на основе значения.

...