优化麦圈,泄漏处理

This commit is contained in:
2025-12-24 18:33:06 +08:00
parent 342cfd347c
commit 84fb05044a
11 changed files with 168 additions and 197 deletions

View File

@@ -256,13 +256,14 @@ public abstract class BaseAppCompatActivity<VDB extends ViewDataBinding> extends
@Override
public void finish() {
EventBus.getDefault().unregister(this);
super.finish();
LogUtils.e(this.getComponentName()+"========finish");
}
@Override
protected void onDestroy() {
EventBus.getDefault().unregister(this);
// 移除背景更新监听器
BackgroundManager.getInstance().removeListener(this);
// 移除颜色变化监听器

View File

@@ -18,6 +18,7 @@ import android.content.Context;
import android.media.projection.MediaProjection;
import android.os.Handler;
import android.os.Looper;
import android.os.SystemClock;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.Display;
@@ -54,7 +55,9 @@ import java.io.FileInputStream;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
@@ -120,6 +123,14 @@ public class AgoraManager {
private Disposable disposableB;
private Disposable disposableC;
// UI 刷新最小间隔ms
private static final long SOUND_UI_INTERVAL = 200;
private final Handler uiHandler = new Handler(Looper.getMainLooper());
private long lastDispatchTime = 0;
// 缓存本次声网回调的音量结果
private final Map<String, Integer> volumeCache = new HashMap<>();
public void setLastRoomId(String value) {
lastRoomId = value;
}
@@ -549,22 +560,33 @@ public class AgoraManager {
if (speakers == null || speakers.length == 0) return;
for (final AudioVolumeInfo info : speakers) {
final int uid = info.uid;
final int volume = info.volume;
// 1⃣ 构建局部 Map声网线程私有
Map<String, Integer> localMap = new HashMap<>();
for (AudioVolumeInfo info : speakers) {
String userId = info.uid > 0
? String.valueOf(info.uid)
: String.valueOf(SpUtil.getUserId());
localMap.put(userId, info.volume);
}
// 回调所有监听器
long now = SystemClock.uptimeMillis();
if (now - lastDispatchTime < SOUND_UI_INTERVAL) return;
lastDispatchTime = now;
// 2⃣ 只把“不可变快照”丢给 UI
uiHandler.post(() -> dispatchVolume(localMap));
}
private void dispatchVolume(Map<String, Integer> volumeSnapshot) {
if (soundLevelUpdateListeners.isEmpty()) return;
for (Map.Entry<String, Integer> entry : volumeSnapshot.entrySet()) {
for (SoundLevelUpdateListener listener : soundLevelUpdateListeners) {
if (listener != null) {
ThreadUtils.runOnUiThread(() -> {
// 远程用户音量变化
listener.onRemoteSoundLevelUpdate(uid > 0 ? String.valueOf(uid) : SpUtil.getUserId() + "", volume);
});
listener.onRemoteSoundLevelUpdate(entry.getKey(), entry.getValue());
}
}
}
}
@Override
public void onLocalVideoStateChanged(Constants.VideoSourceType source, int state, int reason) {
super.onLocalVideoStateChanged(source, state, reason);

View File

@@ -262,99 +262,16 @@ public abstract class BaseWheatView extends ConstraintLayout implements IBaseWhe
AgoraManager.getInstance().addSoundLevelListener(new SoundLevelUpdateListener() {
@Override
public void onRemoteSoundLevelUpdate(String userId, int soundLevel) {
if (mIvRipple == null)
return;
if (mIvRipple == null) return;
if (!userId.equals(pitBean.getUser_id())) return;
if (userId.equals(pitBean.getUser_id())) {
if (soundLevel == 0) {
mIvRipple.pauseAnimation();
CommonAppContext.getInstance().onlineMap.put(pitBean.getUser_id(), 1);
mIvRipple.setVisibility(INVISIBLE);
} else {
mIvRipple.setVisibility(VISIBLE);
mIvRipple.post(() -> {
if (!mIvRipple.isAnimating()) {
if (pitBean.getMic_cycle() != null && !pitBean.getMic_cycle().isEmpty()) {
if (mParser != null) {
mIvRipple.startAnimation();
} else {
mParser = new SVGAParser(getContext());
try {
mParser.decodeFromURL(new URL(pitBean.getMic_cycle()), new SVGAParser.ParseCompletion() {
@Override
public void onError() {
}
@Override
public void onComplete(@NotNull SVGAVideoEntity svgaVideoEntity) {
if (mIvRipple == null)
return;
SVGADrawable drawable = new SVGADrawable(svgaVideoEntity);
mIvRipple.setImageDrawable(drawable);
mIvRipple.startAnimation();
}
});
} catch (MalformedURLException e) {
throw new RuntimeException(e);
}
}
} else {
mIvRipple.startAnimation();
}
CommonAppContext.getInstance().onlineMap.put(pitBean.getUser_id(), 1);
iv_on_line.setVisibility(GONE);
}
});
}
}
boolean nowSpeaking = soundLevel > 0;
updateSpeakingState(nowSpeaking);
}
@Override
public void onLocalSoundLevelUpdate(int volume) {
if (mIvRipple == null)
return;
if (volume == 0) {
mIvRipple.setVisibility(GONE);
} else {
mIvRipple.setVisibility(VISIBLE);
if (!mIvRipple.isAnimating()) {
if (pitBean.getMic_cycle()!=null && !pitBean.getMic_cycle().isEmpty()) {
if (mParser != null) {
mIvRipple.startAnimation();
} else {
mParser = new SVGAParser(getContext());
try {
mParser.decodeFromURL(new URL(pitBean.getMic_cycle()), new SVGAParser.ParseCompletion() {
@Override
public void onError() {
}
@Override
public void onComplete(@NotNull SVGAVideoEntity svgaVideoEntity) {
if (mIvRipple == null)
return;
SVGADrawable drawable = new SVGADrawable(svgaVideoEntity);
mIvRipple.setImageDrawable(drawable);
mIvRipple.startAnimation();
}
});
} catch (MalformedURLException e) {
throw new RuntimeException(e);
}
}
}else {
mIvRipple.startAnimation();
}
CommonAppContext.getInstance().onlineMap.put(pitBean.getUser_id(), 1);
iv_on_line.setVisibility(GONE);
}
}
}
@Override
@@ -379,6 +296,59 @@ public abstract class BaseWheatView extends ConstraintLayout implements IBaseWhe
}
private boolean isSpeaking = false;
private void updateSpeakingState(boolean nowSpeaking) {
// 1⃣ 状态未变化,直接丢弃(核心)
if (nowSpeaking == isSpeaking) return;
isSpeaking = nowSpeaking;
if (!nowSpeaking) {
// 静音状态
mIvRipple.pauseAnimation();
mIvRipple.setVisibility(INVISIBLE);
return;
}
// 2⃣ 开始说话(只触发一次)
mIvRipple.setVisibility(VISIBLE);
iv_on_line.setVisibility(GONE);
CommonAppContext.getInstance().onlineMap.put(pitBean.getUser_id(), 1);
if (!mIvRipple.isAnimating()) {
startRippleAnimation();
}
}
private void startRippleAnimation() {
if (mParser != null) {
mIvRipple.startAnimation();
return;
}
if (pitBean.getMic_cycle() == null || pitBean.getMic_cycle().isEmpty()) {
mIvRipple.startAnimation();
return;
}
try {
mParser = new SVGAParser(getContext());
mParser.decodeFromURL(new URL(pitBean.getMic_cycle()),
new SVGAParser.ParseCompletion() {
@Override
public void onComplete(@NotNull SVGAVideoEntity svgaVideoEntity) {
if (mIvRipple == null) return;
mIvRipple.setImageDrawable(new SVGADrawable(svgaVideoEntity));
mIvRipple.startAnimation();
}
@Override
public void onError() {}
});
} catch (MalformedURLException ignored) {}
}
public void setCharm(String charm) {
mCharmView.setSex(pitBean.getSex(), pitBean.getUser_id(), charm, false);
}