android 在旋转设备时调用了两次回调,但在应用程序启动时调用了一次

8hhllhi2  于 2023-02-02  发布在  Android
关注(0)|答案(1)|浏览(97)

我在Github(https://github.com/alirezaeiii/Movies)中有一个示例,其中我有一个实用程序类来检查Internet网络连接:

class NetworkUtils(context: Context) : ConnectivityManager.NetworkCallback() {

    private val networkLiveData: MutableLiveData<Boolean> = MutableLiveData()

    private val connectivityManager =
        context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager

    fun getNetworkLiveData(): LiveData<Boolean> {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            connectivityManager.registerDefaultNetworkCallback(this)
        } else {
            val builder = NetworkRequest.Builder()
            connectivityManager.registerNetworkCallback(builder.build(), this)
        }

        var isConnected = false

        connectivityManager.allNetworks.forEach { network ->
            val networkCapability = connectivityManager.getNetworkCapabilities(network)

            networkCapability?.let {
                if (it.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)) {
                    isConnected = true
                    return@forEach
                }
            }
        }

        networkLiveData.postValue(isConnected)

        return networkLiveData
    }

    override fun onAvailable(network: Network) {
        networkLiveData.postValue(true)
    }

    override fun onLost(network: Network) {
        networkLiveData.postValue(false)
    }

    fun unRegister() {
        connectivityManager.unregisterNetworkCallback(this)
    }
}

在我在onCreate()和onDestroy()中观察到的unRegisterNetworkCallback活动中:

override fun onCreate() {
        super.onCreate(savedInstanceState)
        handleNetwork()
    }

override fun onDestroy() {
    super.onDestroy()
    networkUtils.unRegister()
}

private fun handleNetwork() {
    networkUtils.getNetworkLiveData().observe(this) { isConnected: Boolean ->
        if (!isConnected) {
            ...
        } else {
            Log.d("Test", "Connected")
            ...
        }
    }
}

我第一次启动应用程序时,“已连接”标签将被调用一次,但当我旋转设备时,它将被调用两次。这是为什么?
我有另一个示例,其中我没有使用Navigation architecture component,当我旋转时它被调用一次:https://github.com/alirezaeiii/TMDb-Paging/blob/master/app/src/main/java/com/sample/android/tmdb/ui/BaseActivity.kt
使用刀柄的供应商:

@Module
@InstallIn(SingletonComponent::class)
class AppUtilsModule {
    @Singleton
    @Provides
    fun provideNetworkUtils(context: Context): NetworkUtils {
        return NetworkUtils(context)
    }
}
i1icjdpr

i1icjdpr1#

由于这是单例。在首次创建活动并调用getNetworkLiveData之后,内部networkLiveData将填充值。在旋转之后,您将使用相同的NetworkUtils对象,该对象已将值存储在networkLiveData中,在注册期间,将返回现有的LiveData,但在返回之前,将有代码向其发布新值。

networkLiveData.postValue(isConnected)

    return networkLiveData

由于postValue是异步调用的,**在大多数情况下,**内部值的更改将在return语句之后调用。
最后,我们注册到livaData,它具有旧值,几毫秒后,我们收到新值。
有几个选项可以避免这种情况:
1.仅在新值与之前的值不同时发布新值(仍不完美)
1.返回实时数据时添加Transformations. distinctUntilChanged(networkLiveData)(仍不完善)
1.修改一些实用程序,并将与观察实时数据相关的逻辑和与从ConnectivityManager接收更新相关的日志分开
编辑:
在registerNetworkCallback之后还有另一个问题,回调是用当前状态调用的,所以再次更新了networkLiveData

相关问题