作为Kotlin和mvvm架构的新手,我浪费了过去两天的时间,没有找到成功的答案。因此,我正在寻找一种干净的解决方案,以在设备在Internet中连接/断开连接时更改片段ui(在我的情况下,它只是一个textview)。我正在使用mvvm架构和android架构组件(viewmodels,livedata,数据绑定...)。我有一个基础活动,其中包含一个底部导航和多个片段。
我正在尝试从自定义广播接收器获取连接事件,并且我想以某种方式在viewmodel或我的片段中传递该事件。
我的第一个想法是使用界面。此接口由广播接收器的onreceive触发,并且在我的片段或视图模型中实现,因此,当发生Internet事件时,textview在我的片段中进行更新。但是我不确定如何在广播接收器中使用该接口,或者即使这是可行的还是好的做法,我也不知道。
我到目前为止所做的就是创建广播接收器
class ConnectionStateObserver: BroadcastReceiver() {
override fun onReceive(p0: Context?, p1: Intent?) {
//somehow use the interface in here
}
}
在我的基本活动中注册/注销
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 ConnectionStatusChange{
fun onChange()
}
并在我的Fragment中实现接口
class myFragment : Fragment(), ConnectionStatusChange {
override fun onChange() {
// do the ui changes here
}
}
我想知道这种方法是否是一种好的做法,以及如何使它可行。如果不可能那样做,那么请给我一些建议(始终赞赏代码!=))。还有一个现代的解决方案,而不是5年的解决方案也将是一件好事。先感谢您。
最终,我找到了想要的一种干净,现代的解决方案。诀窍是将BroadcastReceiver包装在LiveData中。通过使用此模式,您可以直接从片段中观察LiveDada的连接并更新ui。当然,也有可能(如提到的sergiy tikhonov一样)在基本活动中有一个随播对象,该对象带有一个从BroadcastReceiver更新的LiveData,您可以从片段中观察到它,但是我不喜欢这种方法。
所以它是这样的:
用网络状态创建一个枚举。
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)
}
}
最后,我在片段中观察了LiveData。
ConnectionStateLiveData.get(context).observe(viewLifecycleOwner, Observer {
if (it == NetworkAvailability.CONNECTED) {
binding.noInternetTextView.visibility = View.GONE
}
})
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句