此方法onRemoteVideoStateChanged
被异步调用,并且previous_uid
是全局变量,并设置为0。
@Override
public void onRemoteVideoStateChanged(final int uid, int state, int reason, int elapsed) {
super.onRemoteVideoStateChanged(uid, state, reason, elapsed);
runOnUiThread(new Runnable() {
@Override
public void run() {
synchronized (this)
{
if (previous_uid != uid) {
Log.d("TAG", "previous_uid = " + previous_uid + " uid = "+ uid );
setupRemoteVideo(uid);
previous_uid = uid;
}
}
}
});
}
我希望方法
setUpRemoteVideo
仅应使用唯一的uid调用一次。但出乎意料的是,它被多次调用了,这是日志:
2019-11-30 01:24:56.667 D / MY_LOGS:previous_uid = 0 uid = 656786280
2019-11-30 01:24:56.673 D / MY_LOGS:previous_uid = 0 uid = 656786280
最佳答案
您得到的行为实际上是正确的。因为onRemoteVideoStateChanged
调用是异步的,并且可能出现从两个后台异步线程同时调用此函数的情况,所以这解释了您发布的日志。这里的关键思想是if(previous_uid != uid)
不是线程安全的。
您可以创建一个static synchronized
函数,该函数将基于previous_uid
返回true / false,因此通过使该函数成为线程安全函数,可以控制setupRemoteVideo
函数仅针对唯一的uid进行调用。让我尝试给你一个例子。
public class UIDProvider {
private static int uid = 0;
public static synchronized boolean isDifferentThanStoredUid(int uid) {
if (this.uid != uid) {
this.uid = uid; // assign the new value here
return true;
} else {
return false;
}
}
}
现在,可以从
onRemoteVideoStateChanged
首先检查uid
,然后再执行setupRemoteVideo
操作。@Override
public void onRemoteVideoStateChanged(final int uid, int state, int reason, int elapsed) {
super.onRemoteVideoStateChanged(uid, state, reason, elapsed);
runOnUiThread(new Runnable() {
@Override
public void run() {
// The check actually does not provide uniqueness. It justs check with the previous uid as far as I could understand. If you want uniqueness, then you might have to store all the values previously seen in a HashMap and look for the uid in the HashMap.
if (UIDProvider.isDifferentThanStoredUid(uid)) {
Log.d("TAG", "previous_uid = " + previous_uid + " uid = "+ uid );
setupRemoteVideo(uid);
}
}
});
}
我认为这足够了。
关于java - 如何使runOnUiThread同步,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/59110503/