Я изо всех сил пытаюсь выбрать правильный способ передачи данных из broadcastReceiver в ViewModel, и оттуда я передаю данные в свой репозиторий и обновляю LiveData. Я использую push-уведомления FCM и имею локальный broadCastReceiver, который использует ActivityLifecycle.
Я обнаружил, что доступ к ViewModel из BroadcastReceiver - плохая практика, но не знаю почему?
Если я управляю жизненным циклом broadcastReceiver, это не должно вызывать никаких проблем ... Итак, как лучше всего передать полученные данные от FCM в MediatorLiveData моего репозитория? Я использую MediatorLiveData, потому что я добавляю разные источники LiveData (запрос API и FCM).
Буду признателен за совет и правильный способ реализации broadCastReceiver.
Я думал о доступе к репозиторию из BroadCastReceiver, например:
RepositoryMain.getSingletonInstance().setResponse(state);
Вам нужно определить единственный источник истины (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);
}
}
@ViktorVostrikov Я еще не знаком с RxJava, но он записан в моем списке дел
@ XIII-th я следил за этим, но не смог добиться результата, в широковещательном приемнике после обновления живых данных он не запускает репозиторий viewmodel. не могли бы вы помочь мне с этим.
@YBDevi добро пожаловать в мою чат-комнату. Давайте обсудим ваш случай chat.stackexchange.com/rooms/info/107763/xiii-th
@ XIII-th извините, я был отключен от моей работы, не имея возможности проверить мой SO. Когда вы освободитесь, мы можем обсудить эту проблему
Отличная идея создать общедоступный наблюдаемый объект данных в BroadcastReceiver! Для производства я бы рекомендовал перенести взаимодействия с репозиторием в ViewModel для обработки всех запросов данных между сетью и любым локальным хранилищем, таким как база данных Room.
Это нарушает ЧИСТУЮ архитектуру. Действие не должно ничего знать о репозитории, оно должно взаимодействовать только с ViewModel. ViewModel может делегировать репозиторий.
Я думаю, вам не нужен доступ к BroadCastReceiver в модели просмотра. В качестве альтернативы используйте BroadCastReceiver для перемещения данных между действиями. Если вы хотите выполнить какую-либо логику с данными, отправьте их в viewModel, связанный с этим действием.
Простыми словами:
Допустим, у нас есть следующие компоненты:
ActivityOne наблюдает ViewModelOne
ActivityTwo наблюдает ViewModelTwo
BroadCastReceiver [Отправить действия из ActivityOne]. ActivityTwo слушает эти действия
как только ActivityOne получает данные от viewModelOne, он отправляет данные через BroadCastReceiver.
ActivityTwo зарегистрировался для BroadCastReceiver, таким образом, он получает эти действия, если ему необходимо выполнить какую-либо логику с данными, он может отправить его в ViewModelTwo.
Действительно отличная информация! Сделал это аналогичным образом, но по-разному управлял источниками, и я вижу, что ваш способ намного лучше. Однако после реализации бизнес-логики с помощью MediatorLiveData я чувствую, что RxJava может быть лучшим выбором на будущее. С помощью этого инструмента легче объединить разные источники в цепочку. Каков ваш опыт использования RxJava для бизнес-логики вместо MediatorLiveData?