此方法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
答案 0 :(得分:2)
您得到的行为实际上是正确的。因为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);
}
}
});
}
我认为这足够了。