在 Android 视图模型中的内部网络更改回调时 LiveData 未触发 - Kotlin
Posted
技术标签:
【中文标题】在 Android 视图模型中的内部网络更改回调时 LiveData 未触发 - Kotlin【英文标题】:LiveData not firing when Inside Network Change Callbacks in Android View Model - Kotlin 【发布时间】:2021-12-27 02:53:43 【问题描述】:尝试使用实时数据收听连接回调。 回调“onAvailable”和“onLost”被触发,但 ViewModel 中的“postValue”没有被触发。当 AppViewModel 被初始化并且 init 只被调用一次时,它是第一次。 当我将 postData 移到网络回调之外时,它会触发。 任何帮助表示赞赏。
class AppViewModel(application: Application) : androidViewModel(application)
private var connectivityManager =
application.applicationContext.getSystemService(CONNECTIVITY_SERVICE) as ConnectivityManager
var wifiStatusListener = MutableLiveData<Boolean>()
var callback: NetworkCallback =
object : NetworkCallback()
override fun onAvailable(network: Network)
wifiStatusListener.postValue(true) // never calls.
logI(TAG, "onAvailable $network.describeContents()")
override fun onLost(network: Network)
wifiStatusListener.postValue(false) // never calls.
logE(TAG, "onLost $network.describeContents()")
init
logI(TAG, "View Model Initialized")
viewModelScope.launch
initWiFiStatusCheckListener()
// called from init in ViewModel
connectivityManager.registerDefaultNetworkCallback(callback)
在 Activity 中,这就是 View 模型的初始化方式。 下面的日志第一次只调用一次
logI(TAG, "Wifi Listener $it")
appViewModel = ViewModelProvider(this).get(AppViewModel::class.java)
appViewModel.wifiStatusListener.observe(this, Observer
logI(TAG, "Wifi Listener $it")
)
【问题讨论】:
看来代码没有问题。您能帮忙在活动中的registerDefaultNetworkCallback()
和观察wifiStatusListener
上附加更完整的代码吗?
【参考方案1】:
您应该观察 Activity 或 Fragment 的连接性变化。然后在每次回调更改时,您从 ViewModel 传递回调来处理此问题。而且您不需要使用wifiStatusListener
来观察变化。只需获取回调内部的属性即可处理。
请注意,您不应将应用程序上下文传递给 ViewModel。只需在 Activity 中使用当前上下文。
【讨论】:
我明白你在说什么,但你知道为什么 postData 没有在 Network Change 回调中触发吗?谢谢。 我还创建了一个扩展 LiveData 的类,但 postData 仍然不会在网络回调中触发。 您是否尝试过使用setValue()
而不是postValue()
。 postData 被触发,但在后台线程中。参考这里:***.com/questions/51299641/…
我都试过了。没用。
刚发现一篇文章,可以参考一下:medium.com/@kiitvishal89/…【参考方案2】:
如果您的ViewModel
以任何形式使用Context
,我通常会让ViewModel
跟随AndroidLifeCycle
,而不是将Context
存储在ViewModel
中。
//in ViewModel
fun onResume(context : Context)
var connectivityManager = context.getSystemService(CONNECTIVITY_SERVICE) as ConnectivityManager
connectivityManager.registerDefaultNetworkCallback(callback)
fun onPause(context : Context)
var connectivityManager = context.getSystemService(CONNECTIVITY_SERVICE) as ConnectivityManager
connectivityManager.unregisterNetworkCallback(callback)
//in Activity/Fragment
fun onResume()
super.onResume();
viewModel.onResume(requireContext())
fun onPause()
viewModel.onPause(requireContext())
super.onPause();
您也可以将ConnectivityManager
存储在Activity/Fragment
中,然后只传递它而不是上下文,但不要将它存储在ViewModel
中。
【讨论】:
感谢您的回答。这里的问题是 postData 没有从 ViewModel 触发。知道为什么它没有在视图模型的网络回调中触发吗? 您如何确定事件没有触发?您是在连接/断开 wifi 还是蜂窝网络?我的回答更多的是停止将上下文存储在可能导致问题的静态资源(即 ViewModel)中。您遇到的问题似乎不是由此引起的。 我正在连接和断开 wifi 并且回调正在触发,但 postValue 在第一次之后没有触发。 如果您不是从Activity
执行此操作,请尝试将ViewModel
的生命周期所有者交换为Activity
ViewModelProvider(requireActivity()).get(AppViewModel::class.java)
以上是关于在 Android 视图模型中的内部网络更改回调时 LiveData 未触发 - Kotlin的主要内容,如果未能解决你的问题,请参考以下文章