Android MVP中的BroadcastReceiver放在哪里?

Android MVP中的BroadcastReceiver放在哪里?,android,mvp,Android,Mvp,我有一个BroadcastReceiver实现,它接收网络连接事件。它在AndroidManifest.xml中声明,并在网络事件发生时由Android自动调用 广播接收机: public class ConnectivityChangeReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { Log.v(TAG,

我有一个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>

使用上述体系结构,我想知道:

  • 我的广播接收器应该放在哪里

  • 如果我的广播接收器需要写入数据库,那么最好的方法是什么

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

  • 你的广播应该是可视的。然后,它调用Presenter方法,该方法更改某些
    NetworkStateService
    (模型级)的状态。当
    NetworkStateService
    的状态更改时,它会通知演示者网络可用,他们可以提出请求。这些演示者应该更新UI。所有这些演示者都应作为NetworkStateService中的侦听器


    对于长时间的操作,如使用数据库或网络,应启动
    服务
    。原因是广播将在接收10秒后被终止。您应该将演示者放入此
    服务中
    ,并使用此演示者的模型。

    如果您是按功能打包的,您只需在功能包中创建
    receiver
    包,并将
    BroadcastReceiver
    类放入其中即可。如果您没有子包,只需将BroadcastReceiver类放入功能包中。

    如果您需要执行数据库操作/更新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。

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

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

    视图和演示者可以根据运行的程序模式动态更改,例如,您想使用另一个版本的UI,或者更简单的UI行为,但所有逻辑必须保持不变,包括对外部事件的反应。这就是为什么广播接收器应该放在模型中的原因

    您不应该将广播接收器放入活动中,因为活动是(视图)的系统容器,至少如果您遵循MVP模式的话。 如果你的项目相当复杂,可以考虑用一些“外部输入”接口从广播接收器中抽象出来,这在测试过程中很容易被嘲笑,在模型中使用它。
  • 我个人认为,
    BroadcastReceiver
    的事件应该传递给演讲者
  • 根据语句1,演示者引用了应处理db操作的
    交互者
    /
    合同
    /
    用例

    BroadcastReceiver
    --事件-->
    演示者
    -->
    交互者
    -->
    存储库

  • 根据语句1,演示者应该再次使用事件并调用视图

    BroadcastReceiver
    --事件-->
    Presenter
    -->(可能做一些事情,业务逻辑)-->
    查看

  • 以下是我所拥有的,一个简单的示例片段,它总结了我所说的:

      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和观察者模式,如果您将BroadcastReceiver视为外部实体,而不是事件源


    是的,我同意您可以通过去掉
    NetworkInfo
    param来改进该方法。

    使用EventBus怎么样@Rory一个intent服务怎么样?它需要在应用程序流程中显式地启动和停止?@ChintanSoni一大堆乱七八糟的东西怎么办?!;)他试图通过添加“组件”使某些架构不致于快速而肮脏地解决问题,该组件将与所有人交谈并倾听所有人的意见,而无需承担任何义务或签订任何合同。@伊渥克人希望改变看法对您有所帮助;)只是想知道EventBus将属于MVP(或其他架构)的哪一部分…思考它改变了我的看法我相信在代码和活动中注册BroadcastReceiver意味着我的应用程序在不运行时不会接收广播,这是我想要的。是的,it应用程序将不会接收广播,因为调用unregisterReceiver将:1:注销以前注册的BroadcastReceiver。2:已为此广播接收器注册的筛选器将被删除如果这有助于您将此答案标记为最适合其他人的答案。Activity是Android中的纯UI系统容器,这就是为什么如果它修改模型状态,您永远不应该将广播接收器放在其中的原因。这取决于需求。如果您的应用程序希望在应用程序位于前台时使用广播接收器,则您应该按照此处的要求使用此方法。你的两个答案都应该是棒状的,而不是发布不同的内容。你的广播应该是视图-我不知道在什么样的宇宙中这是真的,但在这个宇宙中不是one@TimCastelijns你们能解释一下你们的R宇宙吗?)在我的宇宙中,所有的输入都可以放在视图层,因为它是输入。你也可以把它放在域层。这取决于输入类型。如果用户关闭了网络,则是用户inpu%)