在Android MVP中放置BroadcastReceiver的位置?

时间:2016-09-23 10:52:38

标签: android mvp

我有一个接收网络连接事件的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/

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

  1. 我的BroadcastReceiver应放在哪里?

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

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

5 个答案:

答案 0 :(得分:9)

  1. 我个人认为BroadcastReceiver的事件应该发送给演示者。
  2. 根据语句1,演示者保留对应处理数据库操作的Interactor / Contract / Use case的引用。

    BroadcastReceiver - 事件 - &gt; Presenter - &gt; Interactor ---&gt; Repository

  3. 根据声明1,演示者应该再次使用该事件并调用View。

    BroadcastReceiver - 事件 - &gt; Presenter - &gt; (也许做一些事情,业务逻辑) ---&gt; View

  4. 这是我所拥有的,一个总结我所说的最小示例片段:

      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。

相关问题