在Android MVP中放置BroadcastReceiver的位置?

我有一个接收网络连接事件的BroadcastReceiver实现。 它在AndroidManifest.xml中声明,并在网络事件发生时由Android自动调用。

广播接收器:

public class ConnectivityChangeReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { Log.v(TAG, "action: " + intent.getAction()); Log.v(TAG, "component: " + intent.getComponent()); } } 

AndroidManifest.xml中:

     ...        

我想在这里为我的应用程序使用Google的MVP示例架构:

https://github.com/googlesamples/android-architecture/tree/todo-mvp/

使用上面的架构,只是想知道:

  1. 我的BroadcastReceiver应放在哪里?

  2. 如果我的BroadcastReceiver需要写入数据库,那么最好的方法是什么?

  3. 如果我的BroadcastReceiver需要更新UI,那么最好的方法是什么?

  1. 就个人而言,我相信来自BroadcastReceiver事件应该传递给演示者。
  2. 根据声明1,演示者持有对应处理数据库操作的Interactor / Contract / Use case引用。

    BroadcastReceiver事件 – > Presenter – > Interactor —> Repository

  3. 基于语句1,演示者应该再次使用该事件并调用View。

    BroadcastReceiver事件 – > Presenter – > (可能做一些事情,业务逻辑) —> View

这就是我所拥有的,一个简单的示例片段,总结了我所说的内容:

  private class NetworkBroadcastReceiver23 extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { //... redacted code.../ boolean connected = activeNetworkInfo != null && activeNetworkInfo.isConnected(); mPresenter.onConnectionChanged(activeNetworkInfo,connected); } } 

将接收器放在活动中,因为从那里您将事件流传输到演示者。 这将简化测试演示者的连接更改。 很难实现对平台事件的关注分离,我希望保持我的图层免受android sdk组件和类的影响。 Alex Shutov指出的另一种方法是混合MVP和Observer模式,如果你考虑将BroadcastReceiver视为外部实体,而不是事件源。

是的,我同意您可以通过删除NetworkInfo参数来改进方法。

在MVP设计模式中,模型具有与外部世界连接的所有实体(例如,用于获取数据并在本地持久化的存储库)。 广播接收器是外部事件的输入,最终将修改模型。 良好的比较是六边形架构中的“输入端口”。

Presenter定义了从模型显示数据的方式,但所有业务逻辑,包括对另一个系统或用户事件的反应都应该在模型内部。

View和Presenter可以根据运行的模式程序动态更改,比如说,您想要使用其他版本的UI,或者更简单的UI行为,但所有逻辑必须保持不变,包括对外部事件的反应。 这就是为什么BroadcastReceiver应放在模型中。

你永远不应该将Broadcast接收器放入Activity中,因为Activity是(View)的系统容器,至少如果你遵循MVP模式。 如果您的项目非常复杂,请考虑通过某些“ExternalInput”接口从BroadcastReceiver中抽象,这可以在测试期间轻松模拟并在Model中使用它。

如果按function打包,则只需在function包内创建receiver包,并将BroadcastReceiver类放入其中。 如果您没有子包,只需将BroadcastReceiver类放入function包中。

你的广播应该是观看 。 然后,它调用Presenter方法,该方法更改某些NetworkStateService状态(即Model级别)。 当NetworkStateService状态发生更改时,它会通知Presenters ,该网络可用并且可以发出请求。 这些演示者应该更新UI。 所有这些演示者都应该作为NetworkStateService中的侦听器。

对于长时间操作,例如使用db或network,您应该启动Service 。 原因是广播将在收到后10秒内被杀死。 您应该将Presenter放入此Service并使用此Presenter中的 Model

如果您需要执行数据库操作/更新UI,则应将BroadcastReceiver置于相应的活动中。

这是示例代码。

 public class YourActivity extends AppCompatActivity { @Override protected void onResume() { super.onResume(); registerReceiver(mConnectivityReceiver, new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION)); // public static final String CONNECTIVITY_ACTION = "android.net.conn.CONNECTIVITY_CHANGE"; } @Override protected void onPause() { super.onPause(); unregisterReceiver(mConnectivityReceiver); } public BroadcastReceiver mConnectivityReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { checkIntent(intent); } private void checkIntent(Intent intent) { Bundle bundle = intent.getExtras(); if (bundle != null) { NetworkInfo networkInfo = (NetworkInfo) bundle.get("networkInfo"); doYourStuff(networkInfo.isConnected()); } } }; private void doYourStuff(boolean isNetworkConnected) { //Update your UI here //Do database Operations here } } 

根据网络连接在doYourStuff()中执行您的操作。

通过这种方法,您无需在Menifest.xml文件中注册BroadcastReceiver。