Доступ к BroadCastReceiver в модели просмотра

Я изо всех сил пытаюсь выбрать правильный способ передачи данных из broadcastReceiver в ViewModel, и оттуда я передаю данные в свой репозиторий и обновляю LiveData. Я использую push-уведомления FCM и имею локальный broadCastReceiver, который использует ActivityLifecycle.

Я обнаружил, что доступ к ViewModel из BroadcastReceiver - плохая практика, но не знаю почему?

Если я управляю жизненным циклом broadcastReceiver, это не должно вызывать никаких проблем ... Итак, как лучше всего передать полученные данные от FCM в MediatorLiveData моего репозитория? Я использую MediatorLiveData, потому что я добавляю разные источники LiveData (запрос API и FCM).

Буду признателен за совет и правильный способ реализации broadCastReceiver.

Я думал о доступе к репозиторию из BroadCastReceiver, например:

RepositoryMain.getSingletonInstance().setResponse(state);
20
0
10 451
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Вам нужно определить единственный источник истины (SSoT). В вашем случае это Repository (если Repository инкапсулирует постоянное хранилище db, SSoT это db). Теперь вам нужно реализовать поток данных от приемника для просмотра через SSoT (Repository), как в примере ниже:

Реализация приемника

public class FcmReceiver extends BroadcastReceiver {

    private final MutableLiveData<MyData> mData = new MutableLiveData<>();

    public LiveData<MyData> getData() {
        return mData;
    }

    @Override
    public void onReceive(Context context, Intent intent) {
        // entry point of data
        mData.setValue(new MyData());
    }
}

Репозиторий

public class Repository {

    private static final Repository INSTANCE = new Repository();

    private final MediatorLiveData<MyData> mData = new MediatorLiveData<>();

    private Repository() {}

    public static Repository instance() {
        return INSTANCE;
    }

    public LiveData<MyData> getData() {
        return mData;
    }

    public void addDataSource(LiveData<MyData> data) {
        mData.addSource(data, mData::setValue);
    }

    public void removeDataSource(LiveData<MyData> data) {
        mData.removeSource(data);
    }
}

Посмотреть модель

public class MyViewModel extends ViewModel {

    public LiveData<MyData> getData() {
        // for simplicity return data directly to view
        return Repository.instance().getData();
    }
}

Мероприятия

Есть привязка данных ресивера и Repository

public class MainActivity extends AppCompatActivity {

    private FcmReceiver mReceiver;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mReceiver = new FcmReceiver();
    }

    @Override
    protected void onStart() {
        super.onStart();
        // add data source
        Repository.instance().addDataSource(mReceiver.getData());
        registerReceiver(mReceiver, IntentFilter.create("action", "type"));
    }

    @Override
    protected void onStop() {
        super.onStop();
        // don't forget to remove receiver data source
        Repository.instance().removeDataSource(mReceiver.getData());
        unregisterReceiver(mReceiver);
    }
}

Действительно отличная информация! Сделал это аналогичным образом, но по-разному управлял источниками, и я вижу, что ваш способ намного лучше. Однако после реализации бизнес-логики с помощью MediatorLiveData я чувствую, что RxJava может быть лучшим выбором на будущее. С помощью этого инструмента легче объединить разные источники в цепочку. Каков ваш опыт использования RxJava для бизнес-логики вместо MediatorLiveData?

Viktor Vostrikov 03.08.2018 19:12

@ViktorVostrikov Я еще не знаком с RxJava, но он записан в моем списке дел

XIII-th 05.08.2018 17:14

@ XIII-th я следил за этим, но не смог добиться результата, в широковещательном приемнике после обновления живых данных он не запускает репозиторий viewmodel. не могли бы вы помочь мне с этим.

YBDevi 08.05.2020 13:59

@YBDevi добро пожаловать в мою чат-комнату. Давайте обсудим ваш случай chat.stackexchange.com/rooms/info/107763/xiii-th

XIII-th 08.05.2020 17:41

@ XIII-th извините, я был отключен от моей работы, не имея возможности проверить мой SO. Когда вы освободитесь, мы можем обсудить эту проблему

YBDevi 11.05.2020 09:47

Отличная идея создать общедоступный наблюдаемый объект данных в BroadcastReceiver! Для производства я бы рекомендовал перенести взаимодействия с репозиторием в ViewModel для обработки всех запросов данных между сетью и любым локальным хранилищем, таким как база данных Room.

Adam Hurwitz 24.06.2020 03:11

Это нарушает ЧИСТУЮ архитектуру. Действие не должно ничего знать о репозитории, оно должно взаимодействовать только с ViewModel. ViewModel может делегировать репозиторий.

Christopher Perry 31.10.2020 19:19

Я думаю, вам не нужен доступ к BroadCastReceiver в модели просмотра. В качестве альтернативы используйте BroadCastReceiver для перемещения данных между действиями. Если вы хотите выполнить какую-либо логику с данными, отправьте их в viewModel, связанный с этим действием.

Простыми словами: Допустим, у нас есть следующие компоненты:
ActivityOne наблюдает ViewModelOne
ActivityTwo наблюдает ViewModelTwo
BroadCastReceiver [Отправить действия из ActivityOne]. ActivityTwo слушает эти действия

как только ActivityOne получает данные от viewModelOne, он отправляет данные через BroadCastReceiver.

ActivityTwo зарегистрировался для BroadCastReceiver, таким образом, он получает эти действия, если ему необходимо выполнить какую-либо логику с данными, он может отправить его в ViewModelTwo.

Другие вопросы по теме