Рекомендации BoundService + LiveData + ViewModel в новой рекомендуемой архитектуре Android - PullRequest
0 голосов
/ 19 ноября 2018

Я много думал о том, где разместить Сервисы Android в новой Архитектуре, рекомендованной Android .Я придумал много возможных решений, но я не могу решить, какой из них лучший.

Я провел много исследований и не смог найти ни полезного руководства, ни учебника.Единственный совет, который я нашел о том, где разместить Сервис в архитектуре моего приложения, это @JoseAlcerreca Средний пост

В идеале ViewModels не должна ничего знать о Android.Это улучшает тестируемость, безопасность утечек и модульность.Общее правило заключается в том, чтобы убедиться, что в ваших моделях ViewModels нет импорта android. * (За исключением, например, android.arch. *).То же самое относится и к докладчикам.

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

Теперь я кратко объясню свой сценарий, но только для того, чтобы сделать панораму более четкой, а не потому, что я хочу получить ответ дляэтот конкретный сценарий.

  • У меня есть приложение Android, которое имеет MainActivity со многими фрагментами в нем, все они связаны вместе в BottomNavBar.
  • У меня есть BluetoothService, связанный с myActivityи один из его фрагментов (поскольку я хочу, чтобы у службы был тот же жизненный цикл, что и у Activty, но я также хочу взаимодействовать с ним напрямую из моего фрагмента).
  • Фрагмент взаимодействует с BluetoothService для получения двух типовинформация:
    • Информация о состоянии соединения Bluetooth.Сохранять не нужно.
    • Данные, которые поступают с устройства Bluetooth (это шкала, поэтому вес и состав тела в данном случае).Необходимо сохранить.

Вот три различных архитектуры, о которых я могу подумать:

LiveData внутри AndroidService LiveData inside Android Service arch

  • LiveData с состоянием соединения и измерениями веса, поступающими с устройства Bluetooth, находится внутри службы Bluetooth.
  • Фрагмент может запускать операции вBluetoothService (например, scanDevices)
  • Фрагмент отслеживает LiveData о состоянии соединения и соответствующим образом адаптирует пользовательский интерфейс (например, включает кнопку, если состояние подключено).
  • Фрагментнаблюдает LiveData новых измерений веса.Если из BluetoothDevice приходит новое измерение веса, Fragment затем сообщает собственной ViewModel о необходимости сохранения новых данных.Это делается через класс репозитория.

Общая модель представления между фрагментом и AndroidService Shared ViewModel arch

  • Фрагмент можеттриггерные операции в BluetoothService (например, scanDevices)
  • BluetoothService обновляет связанные с Bluetooth LiveData в общей ViewModel.
  • Фрагмент наблюдает LiveData в своей собственной ViewModel.

Сервис ViewModel Service ViewMOdel arch

  • Фрагмент может запускать операции в BluetoothService (например, scanDevices)
  • BluetoothServiceобновляет связанные с Bluetooth LiveData в своей собственной ViewModel.
  • Фрагмент наблюдает за LiveData в своих собственных ViewModel и BluetoothService ViewModel.

Я почти уверен, что я должен разместить ихна вершине архитектуры и относиться к ним как к действию / фрагменту, потому что BoundServices являются частью Android Framework, они управляютсяОС droid, и они связаны с другими Действиями и Фрагментами.В этом случае я не знаю, как лучше всего взаимодействовать с LiveData, ViewModels и Activity / Fragments.

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

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

Итак, наконец, мой вопрос:

Где мы должны разместить наши Android (связанные) сервисы и как они связаны с другими архитектурными компонентами?Является ли любая из этих альтернатив хорошим подходом?

Ответы [ 3 ]

0 голосов
/ 30 ноября 2018

По моему мнению, Сервис должен быть на том же уровне, что и Активность / Фрагмент , потому что это компонент Framework, а не MVVM .но из-за того, что Сервис не реализует LifecycleOwner и его компонент Android Framework, его не следует рассматривать как источник данных , поскольку он может быть точкой входа вapplication.

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

Такчто должно быть в компоненте архитектуры Android ?Я думаю, вы можете рассматривать это как LifecycleObserver .потому что, независимо от того, что вы делаете в фоновом режиме, вам нужно учитывать жизненный цикл LifecycleOwner .

Почему?потому что мы обычно связываем его с LifecycleOwner (Activity / Fragments) и выполняем долго выполняющиеся задачи из пользовательского интерфейса.Таким образом, его можно рассматривать как LifecycleObserver .Таким образом, мы сделали наш Сервис как " Компонент, поддерживающий жизненный цикл "!


Как вы можете это реализовать?

  1. Возьмите свой класс обслуживания и реализуйте LifecycleObserver интерфейс к нему.

  2. Когда вы привязываете свой сервис к Activity/Fragment, во времяподключение вашего сервиса вашего класса обслуживания, добавьте ваш сервис в свою деятельность как LifecycleObserver, вызвав метод getLifecycle().addObserver(service class obj)

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

Таким образом, нам не потребуется LiveData для обновления с сервиса и даже без ViewModel (Зачем нам это нужно для сервиса? Нам не нужны изменения конфигурации, чтобы выжить на жизненном цикле сервиса. ИОсновная задача для ВМ состоит в том, чтобы составлять данные между жизненным цикломэс) .

Надеюсь, я дал вам понять!

0 голосов
/ 19 января 2019

Один из способов избежать прямого контакта со службой Android и при этом использовать ее - через объект интерфейса.Это часть "I" для сегрегации интерфейса в сокращении SOLID .Вот небольшой пример:

public interface MyFriendlyInterface {
    public boolean cleanMethodToAchieveBusinessFunctionality();
    public boolean anotherCleanMethod();
}

public class MyInterfaceObject implements MyFriendlyInterface {
    public boolean cleanMethodToAchieveBusinessFunctionality() {
        BluetoothObject obj = android.Bluetooth.nastySubroutine();
        android.Bluetooth.nastySubroutineTwo(obj);
    }

    public boolean anotherCleanMethod() {
        android.Bluetooth.anotherMethodYourPresentersAndViewModelsShouldntSee();
    }
}

public class MyViewModel {
    private MyFriendlyInterface _myInterfaceObject;

    public MyViewModel() {
        _myInterfaceObject = new MyInterfaceObject();
        _myInterfaceObject.cleanMethodToAchieveBusinessFunctionality();
    }
}

Учитывая приведенную выше парадигму, вы можете разместить свои услуги в пакете, который находится за пределами ваших пакетов, содержащих код POJO.Не существует «правильного» места для размещения ваших сервисов, но есть определенно НЕПРАВИЛЬНЫЕ места для их размещения (например, куда идет ваш код POJO).

0 голосов
/ 27 ноября 2018

Как насчет того, чтобы относиться к вашим услугам таким образом?

enter image description here

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