开源播放器GSYVideoPlayer + ViewPager2 源码解析

2023-11-30 13:01

本文主要是介绍开源播放器GSYVideoPlayer + ViewPager2 源码解析,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

开源播放器GSYVideoPlayer + ViewPager2 源码解析

  • 前言
  • 一、GSYVideoPlayer🔥🔥🔥是什么?
  • 二、源码解析
    • 1.ViewPager2Activity
  • 总结


在这里插入图片描述

前言

本文介绍GSYVideoPlayer源码中关于ViewPager2 +GSYVideoPlayer 实现的滑动播放列表的实现原理。

本文使用的版本为gsyVideoPlayerVersion = “7.1.4”


一、GSYVideoPlayer🔥🔥🔥是什么?

github地址: https://github.com/CarGuo/GSYVideoPlayer

让我们看看介绍:
视频播放器(IJKplayer、ExoPlayer、MediaPlayer),HTTPS支持,支持弹幕,支持滤镜、水印、gif截图,片头广告、中间广告,多个同时播放,支持基本的拖动,声音、亮度调节,支持边播边缓存,支持视频本身自带rotation的旋转(90,270之类),重力旋转与手动旋转的同步支持,支持列表播放 ,直接添加控件为封面,列表全屏动画,视频加载速度,列表小窗口支持拖动,动画效果,调整比例,多分辨率切换,支持切换播放器,进度条小窗口预览,其他一些小动画效果,rtsp、concat、mpeg。(总结,高端大气上档次)
让我们看看作者:
在这里插入图片描述
让我们看看文档:
在这里插入图片描述

优点

  • 支持好几种开源播放器,集大成者
  • 可以按需引用所需要的依赖,这样一来包体积不会太大
  • 作者维护很勤快,有什么问题issues,作者也会帮忙看看
  • 文档写的很清楚不需要额外查资料,实在不懂代码拉下来一跑,对照着代码基本上就能理解了

缺点:

-有一些版本对应会有不同的问题,比如我使用的时候用了最新的依赖,按照文档不能播放rtsp流,降低了依赖过后就可以播放了。

如果想使用其他播放器的可以看看我的这篇文章

安卓的播放器对比与选型(vlc,EXOplayer,Ijkplayer,GSYVideoPlayer)详细过程

二、源码解析

1.ViewPager2Activity

在ViewPager2Activity中,我们可以看到相关代码。

代码如下(示例):

 viewPagerAdapter = new ViewPagerAdapter(this, dataList);binding.viewPager2.setOrientation(ViewPager2.ORIENTATION_VERTICAL);binding.viewPager2.setAdapter(viewPagerAdapter);binding.viewPager2.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() {@Overridepublic void onPageSelected(int position) {super.onPageSelected(position);//大于0说明有播放int playPosition = GSYVideoManager.instance().getPlayPosition();if (playPosition >= 0) {//对应的播放列表TAGif (GSYVideoManager.instance().getPlayTag().equals(RecyclerItemNormalHolder.TAG)&& (position != playPosition)) {GSYVideoManager.releaseAllVideos();playPosition(position);}}}});binding.viewPager2.post(new Runnable() {@Overridepublic void run() {playPosition(0);}});}

这段代码是在使用Android中的ViewPager2来创建一个滑动页面效果。ViewPager2是Android提供的一个用于实现滑动页面效果的组件。下面是对这段代码的逐行解释:

  1. viewPagerAdapter = new ViewPagerAdapter(this, dataList); 这一行是创建一个ViewPager的适配器,其中this是指当前的Activity,dataList是用来提供数据给ViewPager的列表。
  2. binding.viewPager2.setOrientation(ViewPager2.ORIENTATION_VERTICAL); 这一行是设置ViewPager的滑动方向为垂直滑动。
  3. binding.viewPager2.setAdapter(viewPagerAdapter); 这一行是将刚刚创建的ViewPager适配器设置到ViewPager上。
  4. binding.viewPager2.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() {...}); 这一行是注册一个页面改变的回调。当ViewPager的页面发生改变时,会回调这个接口的实现。
  5. 在回调的实现中,int playPosition = GSYVideoManager.instance().getPlayPosition(); 获取当前播放的位置。
  6. if (playPosition >= 0) {...} 这个判断是为了确认当前有视频播放状态是正常的。
  7. 在这个if语句中,首先判断当前正在播放的视频的Tag是否等于RecyclerItemNormalHolder的Tag,如果不是,那么就释放所有的视频并跳转到当前的位置。这个逻辑是为了处理当页面发生改变时,如果当前播放的视频不在这个页面上,就停止播放并跳转到当前页面的视频。
  8. binding.viewPager2.post(new Runnable() {...}); 这一行代码在ViewPager的Looper中执行一个Runnable,这个Runnable会在ViewPager的UI线程中运行。
  9. 在Runnable的实现中,调用playPosition(0); 方法,是为了在页面加载完成后自动播放位于第一个位置的视频。

在上面的代码中,我们可以看到playPosition这个方法出现了两次,并且从名字中可以看出是播放的方法,我们接下来看看这个方法干了些什么。

    private void playPosition(int position) {binding.viewPager2.postDelayed(new Runnable() {@Overridepublic void run() {RecyclerView.ViewHolder viewHolder = ((RecyclerView) binding.viewPager2.getChildAt(0)).findViewHolderForAdapterPosition(position);if (viewHolder != null) {RecyclerItemNormalHolder recyclerItemNormalHolder = (RecyclerItemNormalHolder) viewHolder;recyclerItemNormalHolder.getPlayer().startPlayLogic();}}}, 50);}

可以看到playPosition通过findViewHolderForAdapterPosition方法找到了当前viewPager2对应的viewHolder,通过viewHolder的getPlayer()方法获取到了播放器,并开始了播放,我们再去看看RecyclerItemNormalHolder类。

package com.example.gsyvideoplayer.holder;import android.content.Context;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;import com.example.gsyvideoplayer.R;
import com.example.gsyvideoplayer.databinding.ActivityDetailExoSubtitlePlayerBinding;
import com.example.gsyvideoplayer.model.VideoModel;
import com.example.gsyvideoplayer.video.SampleCoverVideo;
import com.shuyu.gsyvideoplayer.GSYVideoManager;
import com.shuyu.gsyvideoplayer.builder.GSYVideoOptionBuilder;
import com.shuyu.gsyvideoplayer.listener.GSYSampleCallBack;
import com.shuyu.gsyvideoplayer.video.StandardGSYVideoPlayer;import java.util.HashMap;
import java.util.Map;/*** Created by guoshuyu on 2017/1/9.*/public class RecyclerItemNormalHolder extends RecyclerItemBaseHolder {public final static String TAG = "RecyclerView2List";protected Context context;SampleCoverVideo gsyVideoPlayer;ImageView imageView;GSYVideoOptionBuilder gsyVideoOptionBuilder;public RecyclerItemNormalHolder(Context context, View v) {super(v);this.context = context;gsyVideoPlayer = v.findViewById(R.id.video_item_player);imageView = new ImageView(context);gsyVideoOptionBuilder = new GSYVideoOptionBuilder();}public void onBind(final int position, VideoModel videoModel) {String url;String title;if (position % 2 == 0) {url = "https://pointshow.oss-cn-hangzhou.aliyuncs.com/McTk51586843620689.mp4";title = "这是title";} else {url = "http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4";title = "哦?Title?";}Map<String, String> header = new HashMap<>();header.put("ee", "33");//防止错位,离开释放//gsyVideoPlayer.initUIState();gsyVideoOptionBuilder.setIsTouchWiget(false)//.setThumbImageView(imageView).setUrl(url).setVideoTitle(title).setCacheWithPlay(false).setRotateViewAuto(true).setLockLand(true).setPlayTag(TAG).setMapHeadData(header).setShowFullAnimation(true).setNeedLockFull(true).setPlayPosition(position).setVideoAllCallBack(new GSYSampleCallBack() {@Overridepublic void onPrepared(String url, Object... objects) {super.onPrepared(url, objects);if (!gsyVideoPlayer.isIfCurrentIsFullscreen()) {//静音GSYVideoManager.instance().setNeedMute(true);}}@Overridepublic void onQuitFullscreen(String url, Object... objects) {super.onQuitFullscreen(url, objects);//全屏不静音GSYVideoManager.instance().setNeedMute(true);}@Overridepublic void onEnterFullscreen(String url, Object... objects) {super.onEnterFullscreen(url, objects);GSYVideoManager.instance().setNeedMute(false);gsyVideoPlayer.getCurrentPlayer().getTitleTextView().setText((String) objects[0]);}}).build(gsyVideoPlayer);//增加titlegsyVideoPlayer.getTitleTextView().setVisibility(View.GONE);//设置返回键gsyVideoPlayer.getBackButton().setVisibility(View.GONE);//设置全屏按键功能gsyVideoPlayer.getFullscreenButton().setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {resolveFullBtn(gsyVideoPlayer);}});gsyVideoPlayer.loadCoverImageBy(R.mipmap.xxx2, R.mipmap.xxx2);}/*** 全屏幕按键处理*/private void resolveFullBtn(final StandardGSYVideoPlayer standardGSYVideoPlayer) {standardGSYVideoPlayer.startWindowFullscreen(context, true, true);}public SampleCoverVideo getPlayer() {return gsyVideoPlayer;}
}

为了让读者看的更清晰,我提了整个类,可以看到,在自身初始化时就对gsyVideoPlayer进行了初始化,并且在数据绑定的onBind方法中为了防止错位,专门设置了gsyVideoOptionBuilder,而getPlayer方法只是把gsyVideoPlayer返回。所以,实现列表播放的关键代码其实就是gsyVideoOptionBuilder

 gsyVideoOptionBuilder.setIsTouchWiget(false)//.setThumbImageView(imageView).setUrl(url).setVideoTitle(title).setCacheWithPlay(false).setRotateViewAuto(true).setLockLand(true).setPlayTag(TAG).setMapHeadData(header).setShowFullAnimation(true).setNeedLockFull(true).setPlayPosition(position)

总结

本文主要介绍了开源播放器GSYVideoPlayer和ViewPager2的结合使用,实现滑动播放列表的原理。通过对ViewPager2Activity、RecyclerItemNormalHolder等类中的代码解析,了解了如何在ViewPager2中播放视频,关键代码为gsyVideoOptionBuilder。GSYVideoPlayer支持多种开源播放器,具有较好的维护和文档,但使用时需注意不同版本对应问题。

这篇关于开源播放器GSYVideoPlayer + ViewPager2 源码解析的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/437126

相关文章

Java图片压缩三种高效压缩方案详细解析

《Java图片压缩三种高效压缩方案详细解析》图片压缩通常涉及减少图片的尺寸缩放、调整图片的质量(针对JPEG、PNG等)、使用特定的算法来减少图片的数据量等,:本文主要介绍Java图片压缩三种高效... 目录一、基于OpenCV的智能尺寸压缩技术亮点:适用场景:二、JPEG质量参数压缩关键技术:压缩效果对比

Java调用C++动态库超详细步骤讲解(附源码)

《Java调用C++动态库超详细步骤讲解(附源码)》C语言因其高效和接近硬件的特性,时常会被用在性能要求较高或者需要直接操作硬件的场合,:本文主要介绍Java调用C++动态库的相关资料,文中通过代... 目录一、直接调用C++库第一步:动态库生成(vs2017+qt5.12.10)第二步:Java调用C++

关于WebSocket协议状态码解析

《关于WebSocket协议状态码解析》:本文主要介绍关于WebSocket协议状态码的使用方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录WebSocket协议状态码解析1. 引言2. WebSocket协议状态码概述3. WebSocket协议状态码详解3

CSS Padding 和 Margin 区别全解析

《CSSPadding和Margin区别全解析》CSS中的padding和margin是两个非常基础且重要的属性,它们用于控制元素周围的空白区域,本文将详细介绍padding和... 目录css Padding 和 Margin 全解析1. Padding: 内边距2. Margin: 外边距3. Padd

Oracle数据库常见字段类型大全以及超详细解析

《Oracle数据库常见字段类型大全以及超详细解析》在Oracle数据库中查询特定表的字段个数通常需要使用SQL语句来完成,:本文主要介绍Oracle数据库常见字段类型大全以及超详细解析,文中通过... 目录前言一、字符类型(Character)1、CHAR:定长字符数据类型2、VARCHAR2:变长字符数

使用Jackson进行JSON生成与解析的新手指南

《使用Jackson进行JSON生成与解析的新手指南》这篇文章主要为大家详细介绍了如何使用Jackson进行JSON生成与解析处理,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录1. 核心依赖2. 基础用法2.1 对象转 jsON(序列化)2.2 JSON 转对象(反序列化)3.

Springboot @Autowired和@Resource的区别解析

《Springboot@Autowired和@Resource的区别解析》@Resource是JDK提供的注解,只是Spring在实现上提供了这个注解的功能支持,本文给大家介绍Springboot@... 目录【一】定义【1】@Autowired【2】@Resource【二】区别【1】包含的属性不同【2】@

SpringCloud动态配置注解@RefreshScope与@Component的深度解析

《SpringCloud动态配置注解@RefreshScope与@Component的深度解析》在现代微服务架构中,动态配置管理是一个关键需求,本文将为大家介绍SpringCloud中相关的注解@Re... 目录引言1. @RefreshScope 的作用与原理1.1 什么是 @RefreshScope1.

Java并发编程必备之Synchronized关键字深入解析

《Java并发编程必备之Synchronized关键字深入解析》本文我们深入探索了Java中的Synchronized关键字,包括其互斥性和可重入性的特性,文章详细介绍了Synchronized的三种... 目录一、前言二、Synchronized关键字2.1 Synchronized的特性1. 互斥2.

Python实现无痛修改第三方库源码的方法详解

《Python实现无痛修改第三方库源码的方法详解》很多时候,我们下载的第三方库是不会有需求不满足的情况,但也有极少的情况,第三方库没有兼顾到需求,本文将介绍几个修改源码的操作,大家可以根据需求进行选择... 目录需求不符合模拟示例 1. 修改源文件2. 继承修改3. 猴子补丁4. 追踪局部变量需求不符合很