【问题标题】:LiveData not firing when Inside Network Change Callbacks in Android View Model - Kotlin在 Android 视图模型中的内部网络更改回调时 LiveData 未触发 - 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 上附加更完整的代码吗?

标签: android kotlin android-livedata mutablelivedata


【解决方案1】:

您应该观察 Activity 或 Fragment 的连接性变化。然后在每次回调更改时,您从 ViewModel 传递回调来处理此问题。而且您不需要使用wifiStatusListener 来观察变化。只需获取回调内部的属性即可处理。

请注意,您不应将应用程序上下文传递给 ViewModel。只需在 Activity 中使用当前上下文。

【讨论】:

  • 我明白你在说什么,但你知道为什么 postData 没有在 Network Change 回调中触发吗?谢谢。
  • 我还创建了一个扩展 LiveData 的类,但 postData 仍然不会在网络回调中触发。
  • 您是否尝试过使用setValue() 而不是postValue()。 postData 被触发,但在后台线程中。参考这里:stackoverflow.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)
猜你喜欢
  • 2019-05-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-04-12
  • 2022-07-15
相关资源
最近更新 更多