MMKV-KTX icon indicating copy to clipboard operation
MMKV-KTX copied to clipboard

ANR

Open qwer2y opened this issue 1 year ago • 1 comments

private val mUserStatus by mmkvParcelable<UserStatusModel>(UserStatusModel()).asStateFlow()

mUserStatus.update { value }

这样使用update方法会造成ANR,使用.value不会

qwer2y avatar Jan 10 '25 06:01 qwer2y

问题出在MMKVFlow里的compareAndSet方法

override fun compareAndSet(expect: V, update: V): Boolean =
    flow.compareAndSet(expect, update).also { setSuccess ->
      if (setSuccess) setMMKVValue(value)
    }

第一次更新成功后调用setMMKVValue(value)的时候错误的把value也就是mmkv本地的初始值又给写到mmkv里了,导致后面再调用update方法时候拿到的始终是初始值,而stateflow的update方法

public inline fun <T> MutableStateFlow<T>.update(function: (T) -> T) {
    while (true) {
        val prevValue = value
        val nextValue = function(prevValue)
        if (compareAndSet(prevValue, nextValue)) {
            return
        }
    }
}

prevValue取的是value,拿到的是mmkv初始值,导致StateFlowImpl的updateState中 if (expectedState != null && oldState != expectedState),oldState始终不等于expectedState,再加上update是个死循环方法,最后导致ANR

解决方案就是把setMMKVValue(value)改成setMMKVValue(update)就好了

darriousliu avatar Mar 25 '25 08:03 darriousliu