網(wǎng)站首頁 編程語言 正文
背景
- 現(xiàn)有一個(gè)StateFlow及其監(jiān)聽
private val stateFlow = MutableStateFlow(kotlin.Pair<String, ArrayList<String>>("abc", ArrayList()))
GlobalScope.launch {
stateFlow.collect {
// do something
}
}
- 更新ArrayList并嘗試emit
GlobalScope.launch {
stateFlow.value.second.add("test")
stateFlow.emit(stateFlow.value)
}
實(shí)際上,collect并不會被調(diào)用
原因
MutableStateFlow真正的實(shí)現(xiàn)者是StateFlowImpl, emit方法代碼如下:
override suspend fun emit(value: T) {
this.value = value
}
查看value的set方法:
public override var value: T
get() = NULL.unbox(_state.value)
set(value) { updateState(null, value ?: NULL) }
private fun updateState(expectedState: Any?, newState: Any): Boolean {
var curSequence = 0
var curSlots: Array<StateFlowSlot?>? = this.slots // benign race, we will not use it
synchronized(this) {
val oldState = _state.value
if (expectedState != null && oldState != expectedState) return false // CAS support
if (oldState == newState) return true // Don't do anything if value is not changing, but CAS -> true
_state.value = newState
curSequence = sequence
... 省略部分代碼
}
}
其中"if (oldState == newState) return true"因emit前后是同一個(gè)對象,導(dǎo)致條件為true,那么,如果emit前后不是同一個(gè)對象,即可解決這個(gè)問題?
另一個(gè)問題
emit時(shí)嘗試以下代碼:
GlobalScope.launch {
stateFlow.value.apply {
stateFlow.emit(kotlin.Pair(first, second))
}
}
實(shí)際上,上述代碼仍舊不能解決問題,因?yàn)閗otlin.Pair默認(rèn)重寫了equals方法,查看kotlin.Pair decompiled的Java文件
public final class Pair {
public int hashCode() {
Object var10000 = this.first;
int var1 = (var10000 != null ? var10000.hashCode() : 0) * 31;
Object var10001 = this.second;
return var1 + (var10001 != null ? var10001.hashCode() : 0);
}
public boolean equals(@Nullable Object var1) {
if (this != var1) {
if (var1 instanceof Te.Pair) {
Te.Pair var2 = (Te.Pair) var1;
if (Intrinsics.areEqual(this.first, var2.first) && Intrinsics.areEqual(this.second, var2.second)) {
return true;
}
}
return false;
} else {
return true;
}
}
}
其中Intrinsics.areEqual代碼如下:
public static boolean areEqual(Object first, Object second) {
return first == null ? second == null : first.equals(second);
}
故即使pair對象本身不一樣,但由于kotlin默認(rèn)重寫了equals方法,而pair.first與pair.second是一樣的,從而條件"if (oldState == newState) return true"成立
解決辦法
由于StateFlow源碼無法修改且是特定場景需求,故無法將判斷條件改為kotlin的"===";故使用android.util.Pair或者自定義java Pair class即可
結(jié)論
kotlin class默認(rèn)實(shí)現(xiàn)了equals方法,判斷的是內(nèi)容相等,而Java的class判斷的是地址相等,故判斷對象相等時(shí)需注意此細(xì)節(jié),根據(jù)需求來判斷地址相等(===)還是內(nèi)容相等(==)
原文鏈接:https://juejin.cn/post/7086338636802687006
相關(guān)推薦
- 2024-01-09 JPA查詢——setResultTransformer過期替換
- 2024-03-08 學(xué)習(xí)基于ssm框架前后端分離實(shí)現(xiàn)注冊登錄MD5加密的心得體會
- 2022-12-06 React?Hook中的useEffecfa函數(shù)的使用小結(jié)_React
- 2023-01-19 Scrapy中詭異xpath的匹配內(nèi)容失效問題及解決_python
- 2022-09-16 JQuery實(shí)現(xiàn)電梯導(dǎo)航效果_jquery
- 2023-02-17 docker快速部署zabbix的方法_docker
- 2022-05-23 Python學(xué)習(xí)之時(shí)間包使用教程詳解_python
- 2022-06-11 MSSQL基本語法及實(shí)例操作語句_MsSql
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細(xì)win安裝深度學(xué)習(xí)環(huán)境2025年最新版(
- Linux 中運(yùn)行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎(chǔ)操作-- 運(yùn)算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認(rèn)證信息的處理
- Spring Security之認(rèn)證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權(quán)
- redisson分布式鎖中waittime的設(shè)
- maven:解決release錯(cuò)誤:Artif
- restTemplate使用總結(jié)
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實(shí)現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務(wù)發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結(jié)構(gòu)-簡單動態(tài)字符串(SD
- arthas操作spring被代理目標(biāo)對象命令
- Spring中的單例模式應(yīng)用詳解
- 聊聊消息隊(duì)列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠(yuǎn)程分支