1:修改播放礼物特效
2:修改特效按照ios方式更改
This commit is contained in:
@@ -44,6 +44,8 @@ import java.util.LinkedHashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.Map;
|
||||
import java.util.Queue;
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
|
||||
import okhttp3.Call;
|
||||
import okhttp3.Callback;
|
||||
@@ -121,7 +123,7 @@ public class AvatarFrameView extends FrameLayout {
|
||||
private ChannelSplitRenderer1 renderer;
|
||||
private int mType;//1:循环播放 2:播放一次停止播放
|
||||
private File mFile;
|
||||
private final Queue<PlayItem> playQueue = new LinkedList<>();
|
||||
private final BlockingQueue<PlayItem> playQueue = new LinkedBlockingQueue<>();
|
||||
|
||||
private boolean isPlaying = false;
|
||||
// 添加销毁标记
|
||||
@@ -224,7 +226,7 @@ public class AvatarFrameView extends FrameLayout {
|
||||
return "";
|
||||
}
|
||||
|
||||
private void playNextFromQueue() {
|
||||
public void playNextFromQueue() {
|
||||
// if (isDestroyed) return;
|
||||
// 确保在主线程中执行
|
||||
// if (Looper.myLooper() != Looper.getMainLooper()) {
|
||||
@@ -238,33 +240,39 @@ public class AvatarFrameView extends FrameLayout {
|
||||
return;
|
||||
}
|
||||
// 检查是否可以开始新的播放
|
||||
if (!playbackManager.canStartNewPlayback()) {
|
||||
Logger.d("AvatarFrameView", "Max concurrent playbacks reached, waiting...");
|
||||
return;
|
||||
}
|
||||
// if (!playbackManager.canStartNewPlayback()) {
|
||||
// Logger.d("AvatarFrameView", "Max concurrent playbacks reached, waiting...");
|
||||
// return;
|
||||
// }
|
||||
|
||||
PlayItem item = playQueue.poll();
|
||||
if (item != null) {
|
||||
// 通知开始播放
|
||||
playbackManager.onStartPlayback();
|
||||
isPlaying = true;
|
||||
if (!isPlaying || !isActuallyPlaying()) {
|
||||
|
||||
// 处理播放项目
|
||||
processPlayItem(item);
|
||||
|
||||
} else {
|
||||
isPlaying = false;
|
||||
Logger.d("AvatarFrameView", "Queue is empty, stop playing");
|
||||
PlayItem item = playQueue.poll();
|
||||
if (item != null) {
|
||||
// 通知开始播放
|
||||
playbackManager.onStartPlayback();
|
||||
isPlaying = true;
|
||||
|
||||
// 处理播放项目
|
||||
processPlayItem(item);
|
||||
|
||||
} else {
|
||||
isPlaying = false;
|
||||
Logger.d("AvatarFrameView", "Queue is empty, stop playing");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 添加统一的播放完成处理方法
|
||||
public void onPlaybackComplete() {
|
||||
if (isDestroyed) return;
|
||||
mainHandler.post(() -> {
|
||||
// 再次检查是否已销毁
|
||||
if (isDestroyed) return;
|
||||
|
||||
// 通知播放管理器播放完成
|
||||
playbackManager.onFinishPlayback();
|
||||
// // 通知播放管理器播放完成
|
||||
// playbackManager.onFinishPlayback();
|
||||
|
||||
// 重置播放状态
|
||||
isPlaying = false;
|
||||
@@ -280,19 +288,25 @@ public class AvatarFrameView extends FrameLayout {
|
||||
|
||||
private void processPlayItem(PlayItem item) {
|
||||
try {
|
||||
clearPrevious();
|
||||
// clearPrevious();
|
||||
|
||||
String ext = getFileExtension(item.url);
|
||||
if ("svga".equalsIgnoreCase(ext)) {
|
||||
renderType = RenderType.SVGA;
|
||||
mType = item.type;
|
||||
mBinding.playView.setVisibility(View.GONE);
|
||||
loadSVGA(item.url);
|
||||
mainHandler.post(() -> {
|
||||
renderType = RenderType.SVGA;
|
||||
mType = item.type;
|
||||
if (mBinding != null) {
|
||||
mBinding.playView.setVisibility(View.GONE);
|
||||
}
|
||||
loadSVGA(item.url);
|
||||
} );
|
||||
} else if ("mp4".equalsIgnoreCase(ext)) {
|
||||
renderType = RenderType.MP4;
|
||||
mType = item.type;
|
||||
mBinding.playView.setVisibility(View.VISIBLE);
|
||||
downloadAndPlayMp4(item.url);
|
||||
mainHandler.post(() -> {
|
||||
renderType = RenderType.MP4;
|
||||
mType = item.type;
|
||||
mBinding.playView.setVisibility(View.VISIBLE);
|
||||
downloadAndPlayMp4(item.url);
|
||||
} );
|
||||
} else {
|
||||
// 不支持的格式,直接完成
|
||||
handlePlaybackComplete();
|
||||
@@ -314,8 +328,11 @@ public class AvatarFrameView extends FrameLayout {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isPlaying(){
|
||||
return mBinding.playView.isRunning();
|
||||
public boolean isPlaying() {
|
||||
if (mBinding!=null && mBinding.playView!=null) {
|
||||
return mBinding.playView.isRunning();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
// 在 AvatarFrameView 类中添加以下代码
|
||||
|
||||
@@ -330,24 +347,12 @@ public class AvatarFrameView extends FrameLayout {
|
||||
mainHandler.post(() -> setSource(url, type2));
|
||||
return;
|
||||
}
|
||||
// // 检查内存状态
|
||||
// if (isMemoryLow()) {
|
||||
// LogUtils.w(TAG, "Low memory, skipping animation");
|
||||
// clearQueue();
|
||||
// return;
|
||||
// }
|
||||
// 检查特效是否开启
|
||||
// if (SpUtil.getOpenEffect() != 1) {
|
||||
// // 特效关闭时清空队列并停止播放
|
||||
// clearQueue();
|
||||
// return;
|
||||
// }
|
||||
|
||||
// 添加到播放队列
|
||||
playQueue.add(new PlayItem(url, type2));
|
||||
Logger.d("AvatarFrameView", "Added to queue, queue size: " + playQueue.size() + ", url: " + url);
|
||||
|
||||
if (type2 == 3) {
|
||||
if (type2 == 3 || type2 == 1) {
|
||||
// playNextFromQueue();
|
||||
loadSVGA(url);
|
||||
} else {
|
||||
@@ -461,12 +466,22 @@ public class AvatarFrameView extends FrameLayout {
|
||||
@Override
|
||||
public void onFailure(Call call, IOException e) {
|
||||
LogUtils.e("MP4下载失败: " + e.toString());
|
||||
onPlaybackComplete();
|
||||
mainHandler.post(() -> {
|
||||
// 检查是否已销毁
|
||||
if (!isDestroyed) {
|
||||
onPlaybackComplete();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 更简单的优化版本
|
||||
@Override
|
||||
public void onResponse(Call call, Response response) throws IOException {
|
||||
// 在异步回调中首先检查是否已销毁
|
||||
if (isDestroyed) {
|
||||
LogUtils.w(TAG, "View destroyed before download completed");
|
||||
return;
|
||||
}
|
||||
LogUtils.d("@@@@", "onResponse" + Thread.currentThread().getName());
|
||||
if (response.isSuccessful()) {
|
||||
try (ResponseBody responseBody = response.body()) {
|
||||
@@ -493,31 +508,62 @@ public class AvatarFrameView extends FrameLayout {
|
||||
fos.flush();
|
||||
isTxk = true;
|
||||
mainHandler.post(() -> {
|
||||
LogUtils.d("@@@@Thread", Thread.currentThread().getName());
|
||||
playMp4File(file);
|
||||
// 关键:在执行UI操作前再次检查是否已销毁
|
||||
if (downloadedFile.exists()) {
|
||||
LogUtils.d("@@@@Thread", Thread.currentThread().getName());
|
||||
playMp4File(downloadedFile); // 使用正确的文件引用
|
||||
} else {
|
||||
LogUtils.w(TAG, "View destroyed or file not exist after download");
|
||||
onPlaybackComplete();
|
||||
}
|
||||
});
|
||||
} catch (IOException e) {
|
||||
LogUtils.e("MP4文件保存失败: " + e.getMessage());
|
||||
mainHandler.post(() -> {
|
||||
if (!isDestroyed) {
|
||||
onPlaybackComplete();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
} else {
|
||||
mainHandler.post(() -> onPlaybackComplete());
|
||||
mainHandler.post(() -> {
|
||||
if (!isDestroyed) {
|
||||
onPlaybackComplete();
|
||||
}
|
||||
});
|
||||
}
|
||||
} catch (Exception e) {
|
||||
LogUtils.e("MP4文件保存失败: " + e.getMessage());
|
||||
mainHandler.post(() -> onPlaybackComplete());
|
||||
mainHandler.post(() -> {
|
||||
if (!isDestroyed) {
|
||||
onPlaybackComplete();
|
||||
}
|
||||
});
|
||||
}
|
||||
} else {
|
||||
LogUtils.e("MP4下载响应失败");
|
||||
mainHandler.post(() -> onPlaybackComplete());
|
||||
mainHandler.post(() -> {
|
||||
if (!isDestroyed) {
|
||||
onPlaybackComplete();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
isTxk = true;
|
||||
LogUtils.e("有缓存");
|
||||
playMp4File(file);
|
||||
mainHandler.post(() -> {
|
||||
// 检查是否已销毁
|
||||
if ( file.exists()) {
|
||||
playMp4File(file);
|
||||
} else {
|
||||
LogUtils.w(TAG, "有缓存2222222222222");
|
||||
// onPlaybackComplete();
|
||||
}
|
||||
});
|
||||
// 直接播放缓存文件
|
||||
// if (isTxk) {
|
||||
// mBinding.playView.setLoop(1);
|
||||
@@ -528,8 +574,20 @@ public class AvatarFrameView extends FrameLayout {
|
||||
|
||||
private void playMp4File(File file) {
|
||||
try {
|
||||
if (mBinding != null && file != null && file.exists()) {
|
||||
// mBinding.playView.setAnimListener(new MP4PlaybackCallback());
|
||||
// 双重检查确保组件未被销毁
|
||||
if (isDestroyed) {
|
||||
LogUtils.w(TAG, "Attempt to play MP4 file after view destroyed");
|
||||
onPlaybackComplete();
|
||||
return;
|
||||
}
|
||||
|
||||
if (mBinding == null || mBinding.playView == null) {
|
||||
LogUtils.w(TAG, "PlayView is null");
|
||||
onPlaybackComplete();
|
||||
return;
|
||||
}
|
||||
|
||||
if (file != null && file.exists()) {
|
||||
// 设置循环次数(根据mType决定)
|
||||
if (mType == 1) {
|
||||
mBinding.playView.setLoop(0); // 无限循环
|
||||
@@ -537,9 +595,15 @@ public class AvatarFrameView extends FrameLayout {
|
||||
mBinding.playView.setLoop(1); // 播放一次
|
||||
}
|
||||
|
||||
// 开始播放
|
||||
mBinding.playView.startPlay(file);
|
||||
// 开始播放前检查视图状态
|
||||
if (!isDestroyed && mBinding != null && mBinding.playView != null) {
|
||||
mBinding.playView.startPlay(file);
|
||||
} else {
|
||||
LogUtils.w(TAG, "View was destroyed before MP4 playback started");
|
||||
onPlaybackComplete();
|
||||
}
|
||||
} else {
|
||||
LogUtils.e("播放MP4文件出错: 文件不存在或已损坏");
|
||||
onPlaybackComplete();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
@@ -1265,7 +1329,7 @@ public class AvatarFrameView extends FrameLayout {
|
||||
}
|
||||
|
||||
try {
|
||||
clearPrevious(); // 清除之前的动画
|
||||
// clearPrevious(); // 清除之前的动画
|
||||
svgaSurface.setVisibility(View.VISIBLE);
|
||||
new SVGAParser(getContext()).decodeFromAssets(assetName, new SVGAParser.ParseCompletion() {
|
||||
@Override
|
||||
@@ -1363,7 +1427,7 @@ public class AvatarFrameView extends FrameLayout {
|
||||
|
||||
// 内存检查
|
||||
if (playQueue.size() % 5 == 0) {
|
||||
performLightMemoryCleanup();
|
||||
// performLightMemoryCleanup();
|
||||
}
|
||||
|
||||
// 播放下一个
|
||||
|
||||
@@ -160,7 +160,7 @@ public abstract class BaseWheatView extends ConstraintLayout implements IBaseWhe
|
||||
|
||||
setCardiac(pitBean.getCharm(), getTzbl());
|
||||
setPitData(bean);
|
||||
if (bean.getIs_online() == 2){
|
||||
if (bean.getIs_online() == 2 && bean.getUser_id()!=null && !bean.getUser_id().equals("0") && !bean.getUser_id().isEmpty()){
|
||||
iv_on_line.setVisibility(VISIBLE);
|
||||
}else {
|
||||
iv_on_line.setVisibility(GONE);
|
||||
|
||||
@@ -238,6 +238,16 @@ public class WheatLayoutManager {
|
||||
}
|
||||
}
|
||||
|
||||
public void updateSingleCharm(RoomPitBean pitBean, int pitNumber) {
|
||||
if (pitList == null || pitList.isEmpty() || pitNumber < 1 || pitNumber > 10) return;
|
||||
if (isSingleMode && this.currentSinglePit != pitNumber) return;
|
||||
|
||||
RoomDefaultWheatView wheatView = findWheatViewByPitNumber(pitNumber);
|
||||
if (wheatView != null) {
|
||||
wheatView.setCharm(pitBean.getCharm());
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private RoomDefaultWheatView findWheatViewByPitNumber(int pitNumber) {
|
||||
for (int i = 0; i < container.getChildCount(); i++) {
|
||||
|
||||
@@ -402,6 +402,24 @@ public class WheatLayoutSingManager {
|
||||
}
|
||||
}
|
||||
|
||||
public void upDataCharm(RoomPitBean pitBean, int pitNumber){
|
||||
// 检查容器状态
|
||||
if (container == null || !isContainerValid()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (pitList == null || pitList.isEmpty() || pitNumber < 1 || pitNumber > 10) return;
|
||||
|
||||
// 如果是单个展示模式且不是当前麦位,不处理
|
||||
if (isSingleMode && this.currentSinglePit != pitNumber) return;
|
||||
|
||||
RoomSingSongWheatView wheatView = findWheatViewByPitNumber(pitNumber);
|
||||
if (wheatView != null) {
|
||||
RoomPitBean bean = pitBean;
|
||||
wheatView.setCharm(bean.getCharm()); // 刷新数据
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private RoomSingSongWheatView findWheatViewByPitNumber(int pitNumber) {
|
||||
// 检查容器状态
|
||||
|
||||
@@ -35,8 +35,7 @@
|
||||
android:scaleType="fitCenter"
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible"
|
||||
app:layout_constraintHeight_percent="1"
|
||||
app:layout_constraintWidth_percent="1.05"
|
||||
app:layout_constraintDimensionRatio="1:1"
|
||||
app:layout_constraintBottom_toBottomOf="@id/riv"
|
||||
app:layout_constraintEnd_toEndOf="@id/riv"
|
||||
app:layout_constraintStart_toStartOf="@id/riv"
|
||||
|
||||
Reference in New Issue
Block a user