Совместное использование состояния отображения между представлениями в MVVM без использования синглетонов - PullRequest
0 голосов
/ 12 июня 2019

Мое приложение имеет несколько длительных процессов, которые инициируются пользователем различными фрагментами, и я хотел бы отобразить диалог прогресса, пока они завершаются.Мне бы хотелось, чтобы это диалоговое окно прогресса отображалось между несколькими фрагментами, чтобы нижняя навигация все еще была включена, чтобы у пользователя все еще было чувство готовности, но в противном случае он не может предпринять никаких действительно вредных действий.Большинство моих «основных» фрагментов блокируются таким образом, но другие, такие как настройки и фрагменты справки, не обязательно должны быть.

Мое текущее решение не идеально.Действия инициируются пользователем во фрагменте, но действие становится ответственным за их фактическое выполнение, так что оно может перекрывать диалог прогресса над каждым необходимым фрагментом.Я бы предпочел, чтобы фрагменты отвечали за их собственные задачи.Очевидное разделение интересов становится довольно важным, поскольку размер виртуальной машины деятельности стал огромным, и слишком большая часть бизнес-логики находится в этом классе (и затем соответствующим образом делегируется модели).

например

class MyFragment : Fragment() {
    // MyActivity will implement this interface
    interface NetworkProcess {
        fun start()
    }
    // start() is called on a button click or something similar
}

class MyActivity : AppCompatActivity(), MyFragment.NetworkProcess {
    override fun onCreate(savedInstanceBundle: Bundle?) {
        // Observe state from VM layer
        // Observer updates progress dialog
    }
    override fun start() {
        // Pass action to VM layer
     }
}

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

например,

class MyFragment : Fragment() {
    // MyActivity will implement this interface
    interface NetworkProcessDialog {
        fun update(text: Int)
        fun stop()
    }
    override fun onActivityCreated() {
        // Observe state from viewmodel
        // Set listener on a button send action to viewmodel to start process
    }
}

class MyActivity : AppCompatActivity(), MyFragment.NetworkProcessDialog {
    override fun updateDialog(text: Int) {
        // Make dialog visible if not and show update
     }
    override fun stopDialog() {
        // Make dialog invisible
    }
}

Другое решение, о котором я подумал, - это вставить состояние просмотра в слой модели.Кажется, однако, что для этого потребуется одноэлементная (и куча параллельная защита), чтобы модели представления не могли начать перезаписывать состояние, так как оно находится в процессе выполнения одной из этих длительных задач.В настоящее время этого избегают автоматически, поскольку только одна виртуальная машина действия обрабатывает всю работу.

Итак, возможно ли разделить задачи такого рода, не полагаясь на синглтоны на уровне модели?

1 Ответ

1 голос
/ 12 июня 2019

У меня не было бы активности (и фрагментов) такой ответственности.Они представляют собой policyDelegates (имя, используемое Google) для вещей, от которых вы не можете избавиться (вам НУЖНО одно или другое, чтобы ваше приложение функционировало).Поэтому им следует делать только то, что они знают лучше:

  • Обрабатывать жизненный цикл (не может обойти это)
  • Раздувать представления и отображать их
  • Сохранять / восстанавливать своисостояния (когда это возможно)
  • Интерфейс между фрагментами (если необходимо)
  • Получать обновления состояний и отражать это в соответствующих представлениях
  • и т. д.

Так что бы я сделал?

  • Имеет LongProcessesManager (имя вас старше 2), который способен запускать, останавливать и управлять N числом «процессов».Он также должен предлагать способы индикации прогресса указанного процесса.
  • Иметь ProcessFragment, способный использовать указанный менеджер для запуска, и получать обновления для процесса (и он может влиять на указанные результаты, например, обновлять индикатор выполнения).
  • Если вам нужно отобразить прогресс GLOBAL, вы также можете сделать это, ваша деятельность может содержать более 1 фрагмента, так что ничто не мешает вам разместить второй фрагмент на экране, который не исчезает во время прогресса(например, музыкальный проигрыватель) или что-то еще, я не знаю ваш пользовательский интерфейс:)
  • Подумайте о том, чтобы переместить управление упомянутым Менеджером в Службу, которая может стать Foreground, если это требуется (пользователь нажимает "Главная страница")."или отойти от вашего приложения, чтобы выбрать телефонный звонок или проверить Instagram, пока они ожидают ваших LONG запущенных процессов).
  • Используйте DependencyInjection (Dagger, Koin, вы выбираете), чтобы у вас был один экземпляр этого менеджера, который вставляется во все фрагменты (или Shared ViewModels, если хотите).

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

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