I am struggling in choosing the right way to pass data from broadcastReceiver to ViewModel and from there I pass data to my Repository and update LiveData. I use FCM push notifications and have local broadCastReceiver which uses ActivityLifecycle.
I found that it is bad practice to access ViewModel from BroadcastReceiver, but not sure why?
If I manage lifecycle of broadcastReceiver it should not cause any problems... So what is the best way to pass received data from FCM to my Repository's MediatorLiveData? I use MediatorLiveData, because I add different LiveData sources(API request and FCM).
Would be grateful for advice and correct way of implementing broadCastReceiver.
I have thought about accessing Repository from BroadCastReceiver, like this:
RepositoryMain.getSingletonInstance().setResponse(state);
You need to define single source of truth (SSoT). In your case it Repository
(if Repository
encapsulate db persistence storage, SSoT it is db). Now you need to implement data flow from receiver to view through SSoT (Repository
) like in example below:
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();
}
}
There is binding of receiver data and 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);
}
}