我有一个接收网络连接事件的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:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.test">
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
...
<receiver
android:name=".ConnectivityChangeReceiver"
android:enabled="true">
<intent-filter>
<action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
</intent-filter>
</receiver>
</application>
</manifest>
我想在这里为我的应用程序使用Google的MVP示例架构:
https://github.com/googlesamples/android-architecture/tree/todo-mvp/
使用上述架构,只是想知道:
我的BroadcastReceiver应放在哪里?
如果我的BroadcastReceiver需要写入数据库,那么最好的方法是什么?
如果我的BroadcastReceiver需要更新UI,那么最好的方法是什么?
答案 0 :(得分:9)
BroadcastReceiver
的事件应该发送给演示者。根据语句1,演示者保留对应处理数据库操作的Interactor
/ Contract
/ Use case
的引用。
BroadcastReceiver
- 事件 - &gt; Presenter
- &gt; Interactor
---&gt; Repository
根据声明1,演示者应该再次使用该事件并调用View。
BroadcastReceiver
- 事件 - &gt; Presenter
- &gt; (也许做一些事情,业务逻辑) ---&gt; 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
参数来改进该方法。
答案 1 :(得分:3)
在MVP设计模式中,Model具有与外部世界连接的所有实体(例如,用于获取数据并在本地持久保存的Repository)。广播接收器是外部事件的输入,最终将修改模型。良好的比较是一个输入端口&#39;在六角形建筑中。
Presenter定义了从模型显示数据的方式,但所有业务逻辑,包括对另一个系统或用户事件的反应都应该在模型内部。
View and Presenter可以动态更改,具体取决于运行的模式程序,例如,您想要使用其他版本的UI,或更简单的UI行为,但所有逻辑必须保持不变,包括对外部事件的反应。这就是为什么BroadcastReceiver应放在模型中。
你永远不应该将Broadcast接收器放入Activity中,因为Activity是(View)的系统容器,至少如果你遵循MVP模式。 如果您的项目非常复杂,请考虑通过一些&#39; ExternalInput&#39;从BroadcastReceiver中抽象出来。接口,可以在测试过程中轻松模拟,并在模型中使用。
答案 2 :(得分:0)
如果按功能打包,则只需在功能包内创建receiver
包,并将BroadcastReceiver
类放入其中。如果您没有子包,只需将BroadcastReceiver
课程放入功能包中即可。
答案 3 :(得分:-3)
您的广播应该是查看。然后,它调用 Presenter 方法,该方法更改某些NetworkStateService
( Model 级别)的状态。当状态NetworkStateService
发生更改时,它会通知演示者,该网络可用并且可以发出请求。这些演示者应该更新UI。 所有这些演示者都应该成为NetworkStateService中的侦听器。
对于长时间操作,例如使用db或network,您应该启动Service
。原因是广播将在收到10秒后被杀死。您应该将 Presenter 放入此Service
并使用此演示者中的模型。
答案 4 :(得分:-3)
如果您需要执行数据库操作/更新UI,则应将BroadcastReceiver置于相应的活动中。
以下是示例代码。
order by
根据网络连接在doYourStuff()中处理您的内容。
通过这种方法,您无需在Menifest.xml文件中注册BroadcastReceiver。