android - 从 MvvM 架构和 Kotlin 中的广播接收器更新 fragment ui

标签 android android-fragments kotlin mvvm broadcastreceiver

作为 kotlin 和 mvvm 架构的新手,我浪费了过去两天来寻找这个问题的答案,但没有任何成功。所以我正在寻找一个干净的解决方案来更改 fragment ui(在我的情况下它只是一个 TextView ),当设备在互联网上连接/断开时。我正在使用 mvvm 架构和 android 架构组件(viewmodels、livedata、数据绑定(bind)......)。我有一个带有底部导航和多个 fragment 的基本 Activity 。

我正在尝试从自定义广播接收器获取连接事件,并且我想以某种方式在 View 模型或我的 fragment 中传递该事件。

我的第一个想法是使用接口(interface)。此接口(interface)由广播接收器的 onreceive 触发,并在我的 fragment 或 View 模型中实现,因此当互联网事件发生时, TextView 在我的 fragment 中更新。但是我不确定如何在广播接收器中使用该接口(interface),或者我不知道这是否可行或一个好的做法。

到目前为止我所做的是创建广播接收器

class ConnectionStateObserver: BroadcastReceiver() {
    override fun onReceive(p0: Context?, p1: Intent?) {
       //somehow use the interface in here
    }
}


在我的基本 Activity 中注册/注销它
    override fun onResume() {
        super.onResume()
        val broadcastIntent = IntentFilter()
        broadcastIntent.addAction(ConnectivityManager.CONNECTIVITY_ACTION)
        registerReceiver(ConnectionStateObserver(), broadcastIntent)
    }
    override fun onPause() {
        super.onPause()
        unregisterReceiver(ConnectionStateObserver())
    }

(我知道 ConnectivityManager.CONNECTIVITY_ACTION 已被弃用,但我找不到更好的解决方案)。

创建接口(interface)
interface ConnectionStatusChange{
    fun onChange()
}

并在我的 fragment 中实现接口(interface)
class myFragment : Fragment(), ConnectionStatusChange {
override fun onChange() {
        // do the ui changes here
    }
}

我想知道这种方法是否是一种好的做法,以及如何使其发挥作用。如果不可能这样做,请给我一些建议(代码总是很感激!=))。此外,最好有一个现代的,而不是 5 年前的解决方案。先感谢您。

最佳答案

最终我找到了一个我想要的干净和现代的解决方案。诀窍是将 BroadcastReceiver 包装在 LiveData 中。通过使用此模式,您可以直接从 fragment 中观察连接 LiveDada 并更新 ui。当然,也有可能(就像提到的 sergiy tikhonov 一样)在基础 Activity 中有一个伴随对象,其 LiveData 从 BroadcastReceiver 更新,您可以从 fragment 中观察它,但我不喜欢这种方法。

所以它是这样工作的:

创建一个包含网络状态的枚举。

enum class NetworkAvailability {
    UNKNOWN,
    CONNECTED,
    DISCONNECTED
}

创建扩展 LiveData 的类。我正在使用单例模式,因为我不想要多个实例。我创建了一个 BroadcastReceiver 实例,并在 LiveData 的 onActive 和 onInactive 方法中注册/取消注册它。
class ConnectionStateLiveData(val context: Context) : LiveData<NetworkAvailability>() {

    companion object {
        private lateinit var instance: ConnectionStateLiveData

        fun get(context: Context): ConnectionStateLiveData {
            instance = if (::instance.isInitialized){
                instance
            }else{
                ConnectionStateLiveData(context)
            }
            return instance
        }
    }

    private val connectivityBroadcastReceiver = object : BroadcastReceiver() {
        override fun onReceive(p0: Context?, p1: Intent?) {
            val connectivityManager =
                context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
            val netInfo = connectivityManager.activeNetworkInfo

            value = if (netInfo != null && netInfo.isConnected) {
                NetworkAvailability.CONNECTED
            } else {
                NetworkAvailability.DISCONNECTED
            }
        }
    }

    override fun onActive() {
        super.onActive()
        value = NetworkAvailability.UNKNOWN
        val broadcastIntent = IntentFilter()
        broadcastIntent.addAction(ConnectivityManager.CONNECTIVITY_ACTION)
        context.registerReceiver(connectivityBroadcastReceiver, broadcastIntent)
    }

    override fun onInactive() {
        super.onInactive()
        context.unregisterReceiver(connectivityBroadcastReceiver)
    }
}

最后,我观察了 fragment 中的 LiveData。
ConnectionStateLiveData.get(context).observe(viewLifecycleOwner, Observer {
                if (it == NetworkAvailability.CONNECTED) {
                    binding.noInternetTextView.visibility = View.GONE
                }
            })

关于android - 从 MvvM 架构和 Kotlin 中的广播接收器更新 fragment ui,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61226618/

相关文章:

Android 5.0 Lollipop UsbDevice 缺少接口(interface)

android - 限制用户可以在 Mapview 上访问的区域

android - 没有 ActionBar 的基于 fragment 的选项卡

android - 将复选框的值从 fragment 获取到另一个不是 Activity 的类

android - 在 java 类中访问 Kotlin 中定义的常量

java - 在 Java Android 应用程序中使用 Kotlin 代码

java.lang.NumberFormatException : unable to parse String as integer 异常

android - ViewPager在包含相机的滑动上显示黑屏

android - 在 Android Viewpager 中更改 pagetitle

android - 更改应用程序语言