TL;此问题的DR:
<块引用>是否有可能将用于 const wait = ms =>
new Promise(resolve => setTimeout(resolve, ms))
;
const watch = async (predicate, ms) => {
for (;; await wait(ms)) {
const result = await predicate();
if (result) {
return result;
}
}
};
/* mock the API for demonstration purposes */
const checkOrderStatus = (() => {
let calls = 0;
return async () => ({
status: ++calls === 3 ? "FILLED" : false
});
})();
const watchFill = (asset, orderId) =>
watch(async () => {
const {status} = await checkOrderStatus();
console.log(`Order status: ${status}`);
return status === "CANCELLED" ? false : status === "FILLED";
}, 1000)
;
const sellOrder = async () => {
try {
const orderIsFilled = await watchFill();
console.log("orderIsFilled:", orderIsFilled);
}
catch (err) {
console.error('Err sellIfFilled() :', err);
}
};
sellOrder();
和 LiveData
的 ViewModel 中带有 backing property (MutableLiveData)
的 Observe
ArrayList 可以有竞争条件,需要使用 Add
还是 Synchronized
?
假设 ArrayList 将从回调中获取其值
我正在尝试使用 Agora Android SDK 设置群组视频通话。我遵循了文档 here。问题出在 IRtcEngineEventHandler 中的 Lock
。
OnUserJoined 回调
callbacks (onUserJoined, onUserOffline)
<块引用>
onUserOffline 回调
mRtcEngine = RtcEngine.create(baseContext, APP_ID, object : IRtcEngineEventHandler() {
override fun onUserJoined(uid: Int, elapsed: Int) {
// onUserJoined callback is called anytime a new remote user joins the channel
super.onUserJoined(uid, elapsed)
// We mute the stream by default so that it doesn't consume unnecessary bandwidth
mRtcEngine?.muteRemoteVideoStream(uid, true)
// We are using a lock since uidList is shared and there can be race conditions
lock.lock()
try {
// We are using uidList to keep track of the UIDs of the remote users
uidList.add(uid)
} finally {
lock.unlock()
}
此处使用 override fun onUserOffline(uid: Int, reason: Int) {
// onUserOffline is called whenever a remote user leaves the channel
super.onUserOffline(uid, reason)
// We use toRemove to inform the RecyclerView of the index of item we are removing
val toRemove: Int
// We are using a lock since uidList is shared and there can be race conditions
lock.lock()
try {
// We are fetching the index of the item we are about to remove and then remove the item
toRemove = uidList.indexOf(uid)
uidList.remove(uid)
} finally {
lock.unlock()
}
以 Lock
方式访问 uidlist
以防止 thread safe
。当我完全遵循文档时,它对我有用,但是当我尝试在 race condition
中使用带有 LiveData
的 backing property (MutableLiveData)
来保存 ViewModel
时,观察者在uidlist
总是返回一个空列表。
我的视图模型
uidlist
}
我在 class MainViewModel: ViewModel() {
private val _uidList: MutableLiveData<ArrayList<Int>> = MutableLiveData()
val uidList: LiveData<ArrayList<Int>> get() = _uidList
init {
_uidList.value = ArrayList<Int>()
}
fun addToUserList(uid: Int) {
_uidList.value?.add(uid)
Log.d("adding user ","$uid")
}
fun removeFromUserList(uid: Int) {
_uidList.value?.remove(_uidList.value!!.indexOf(uid))
}
内调用 addToUserList()
,在 onUserJoined()
} 内调用 removeFromUserList()
请指导我解决这个问题,
谢谢
答案 0 :(得分:2)
你不应该改变存储在 LiveData
中的值,你会得到非常奇怪的行为。您必须完全换出该值。
我有点懒惰,所以我只是给你答案。
class MainViewModel: ViewModel() {
private val _uidList: MutableLiveData<List<Int>> = MutableLiveData()
val uidList: LiveData<List<Int>> get() = _uidList
init {
_uidList.value = emptyList<Int>()
}
fun addToUserList(uid: Int) {
_uidList.value = (_uidList.value ?: emptyList()) + uid
Log.d("adding user ","$uid")
}
fun removeFromUserList(uid: Int) {
val value = _uidList.value?.toMutableList()
if (value == null) return
value.remove(value.indexOf(uid))
_uidList.value = value
}