在Viewmodel中访问BroadCastReceiver

Vik*_*kov 7 android mvvm viewmodel android-livedata android-architecture-components

我真的很难选择正确的方法将数据从broadcastReceiver传递到ViewModel,并从那里我将数据传递给我的存储库并更新LiveData.我使用FCM推送通知,并使用ActivityLifecycle的本地broadCastReceiver.我发现从BroadcastReceiver访问ViewModel是不好的做法,但不确定为什么?如果我管理broadcastReceiver的生命周期,它不应该导致任何问题...... 那么将接收到的数据从FCM传递到我的Repository的MediatorLiveData的最佳方法是什么?我使用MediatorLiveData,因为我添加了不同的LiveData源(API请求和FCM).将不胜感激的建议和实施broadCastReceiver的正确方法.我考虑过从BroadCastReceiver访问Repository,如下所示:

RepositoryMain.getSingletonInstance()setResponse(状态).

XII*_*-th 13

您需要定义单一事实来源(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());
    }
}
Run Code Online (Sandbox Code Playgroud)

知识库

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

查看模型

public class MyViewModel extends ViewModel {

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

活动

有接收器数据和绑定 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);
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 这违反了 CLEAN 架构。Activity 不应该知道有关 Repository 的任何信息,它应该只与 ViewModel 通信。ViewModel 可以委托给存储库。 (4认同)
  • 在 BroadcastReceiver 中创建公共可观察数据对象是个好主意!对于生产,我建议将存储库交互移至 ViewModel,以处理网络和任何本地存储(如 Room 数据库)之间的所有数据请求。 (3认同)
  • 真的很棒的信息!是以类似的方式做到的,但是管理源的方式不同,我发现你的方式要好得多。然而,在使用 MediatorLiveData 实现业务逻辑之后,我觉得 RxJava 可能是未来更好的选择。使用该工具可以更轻松地链接不同的源。您使用 RxJava 代替 MediatorLiveData 来处理业务逻辑的体验如何? (2认同)