开源播放器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支持多种开源播放器,具有较好的维护和文档,但使用时需注意不同版本对应问题。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/209238.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

linux 内核regulator

问题 在sys文件系统下没有生成cpu 调频的相关节点。 日志对比 [ 3.588745] cpu cpu4: Looking up cpu-supply from device tree [ 3.588753] cpu cpu4: Failed to get reg [ 3.588791] cpu cpu4: Looking up cpu-supply from device tree [ 3.588808] Failed to i…

C语言练习题

C语言练习题 文章目录 C语言练习题题目一题目二题目三题目四题目五题目六题目八 题目一 #include <stdio.h> //VS2022,默认对齐数为8字节 union Un {short s[7];int n; };int main() {printf("%zd", sizeof(union Un));return 0; }代码运行结果:> 16 sizeo…

MySQL双主双从数据库集群搭建

1 引言 在之前的文章中提到过单主单从的搭建方法&#xff0c;具体请参考《MySQL主从数据库搭建》这篇文章&#xff0c;本文主要讲述双主双从&#xff0c;双主多从集群的搭建方式。 这里要问一个问题&#xff0c;为什么MySQL要搭建数据库集群呢&#xff1f;我想应该有以下几点原…

彻底解决ModuleNotFoundError: No module named ‘exceptions‘【Bug完美解决】

文章目录 项目场景:问题描述原因分析:解决方案:此Bug解决方案总结心得项目场景: 根据本文可找到bug原因并彻底解决**ModuleNotFoundError: No module named ‘exceptions‘**Bug 报错: E:\Anconda\python.exe c:\Users\24190\PycharmProjects\pythonProject4py尝试 gong…

Android textView 显示: STRING_TOO_LARGE

在Android中&#xff0c;字符串资源的长度限制是32KB&#xff0c;getString()方法返回的字符串资源的大小超过这个限制&#xff0c;就会抛出STRING_TOO_LARGE 这个错误。 我本地的临界值是&#xff1a;32.3 KB (33,090 字节) 小于等于33090时&#xff0c;能正常显示&#xff…

数据结构和算法-树与二叉树的存储结构以及树和二叉树和森林的遍历

文章目录 二叉树的存储结构二叉树的顺序存储二叉树的链式存储小结 二叉树的先中后序遍历例题小结 二叉树的层次遍历小结 由遍历序列构造二叉树一个遍历序列即使给定了前中后序&#xff0c;也不能确定该二叉树的形态可以确定的序列组合前序中序后序中序层序中序 小结若前序&…

构建第一个ArkTS应用(纯HarmonyOS应用)

1. 安装开发工具 在华为开发者官方上下载HarmonyOS应用专用的开发工具&#xff0c;链接地址&#xff1a;HUAWEI DevEco Studio和SDK下载和升级 | HarmonyOS开发者 要想使用开发工具让项目跑起来&#xff0c;需要10G的磁盘空间。开发工具需要的磁盘空间为2.36G&#xff1b;SDK需…

springBoot整合task

springBoot整合task 文章目录 springBoot整合task开开关设置任务&#xff0c;并设置执行周期定时任务的相关配置 开开关 设置任务&#xff0c;并设置执行周期 Component public class MyBean {Scheduled(cron "0/1 * * * * ?")public void print(){System.out.prin…

Shutdown Signal: channel error; protocol method: #method<channel.close>

完整异常信息&#xff1a; Shutdown Signal: channel error; protocol method: #method<channel.close>(reply-code404, reply-textNOT_FOUND - no exchange fanoutExchange in vhost /, class-id60, method-id40) 意思是找不到名字是 fanoutExchange 的虚拟机 就是虚拟机…

JVM基础篇:垃圾回收

目录 1.前言 1.1C/C的内存管理 1.2Java的内存管理 2.方法区的回收 3.堆回收 3.1引用计数法和可达性分析法 3.2五种对象引用 强引用 软引用 弱引用 虚引用 终结器引用 3.3垃圾回收算法评价标准 ①吞吐量 ②最大暂停时间 ③堆使用效率 3.4垃圾回收算法 ①标记清…

RabbitMQ 笔记

Message durability 确保消息在server 出现问题或者recovery能恢复&#xff1a; declare it as durable in the producer and consumer code. boolean durable true; channel.queueDeclare("hello", durable, false, false, null);Queue 指定 //使用指定的queue&…

【古月居《ros入门21讲》学习笔记】14_参数的使用与编程方法

目录 说明&#xff1a; 1. 参数模型&#xff08;全局字典&#xff09; 2. 实现过程&#xff08;C&#xff09; 创建功能包 参数命令行的使用 YAML参数文件 rosparam命令 使用示例 编程方法&#xff08;C&#xff09; 配置代码编译规则 编译并运行 编译 运行 3. 实…

基于springboot + vue体育馆使用预约平台

qq&#xff08;2829419543&#xff09;获取源码 开发语言&#xff1a;Java Java开发工具&#xff1a;JDK1.8 后端框架&#xff1a;springboot 前端&#xff1a;采用vue技术开发 数据库&#xff1a;MySQL5.7和Navicat管理工具结合 服务器&#xff1a;Tomcat8.5 开发软件&#xf…

Wireshark 协议插件Lua开发 -数据包内嵌协议的解释

概述 因为公司项目涉及的协议打包&#xff0c;协议包内又嵌了一层IP包的奇葩套娃结构&#xff0c;为了方便抓包调试&#xff0c;利用Wireshark的协议插件开发功能&#xff0c;写了一个插件&#xff0c;博文记录以备忘。 环境信息 Wireshark 4.0.3 协议结构体套娃图 插件安装…

C++基础 -35- string类

string类的格式 string a;如下图&#xff0c;使用string类比常规的字符串处理方便很多 而且需要进行的字符串处理&#xff0c;在类中都能完成 #include "iostream"using namespace std;extern "C" {#include "string.h" }int main() {//c的写…

从零开始:PHP实现阿里云直播的简单方法!

1. 配置阿里云直播的推流地址和播放地址 使用阿里云直播功能前&#xff0c;首先需要在阿里云控制台中创建直播应用&#xff0c;然后获取推流地址和播放地址。 推流地址一般格式为&#xff1a; rtmp://{Domain}/{AppName}/{StreamName}?auth_key{AuthKey}-{Timestamp}-{Rand…

C# 使用HtmlAgilityPack解析提取HTML内容

写在前面 HtmlAgilityPack是一个HTML解析类库&#xff0c;日常用法就是爬虫获取到内容后&#xff0c;先用XPath获取目标节点&#xff0c;再用正则进行匹配&#xff1b;使用XPath的目的主要是将目标节点或内容限定在一个较小的范围&#xff0c;如果一上来就用正则那效率肯定不…

Git Bash环境下用perl脚本获取uuid值

在Linux环境下&#xff0c;比如在ubuntu就直接有uuidgen命令直接获取uuid值。在Windows环境下常用的git bash中没有对应的命令&#xff0c;略有不便。这里用脚本写一个uuidgen&#xff0c;模拟Linux环境下的uuidgen命令。 #! /usr/bin/perl use v5.14; use Win32;sub uuidGen {…

Windows驱动中校验数字签名(使用 ci.dll)

1.背景 对于常规应用程序来说&#xff0c;校验数字签名认证在应用层可以使用 WinVerifyTrust, 在驱动层使用常规的 API无法使用&#xff0c;自己分析数据又太麻烦。 在内核中 ci.dll 包装了数据签名验证相关的功能&#xff0c;我们可以使用该 dll 来实现我们的数字签名验证。 详…

Blender学习笔记:小车狂奔动画

文章目录 路旁小树汽车尾气移动 教程地址&#xff1a;八个案例教程带你从0到1入门blender【已完结】 小车建模 路旁小树 1 添加摄像机&#xff0c;在小车下面拉一个平面&#xff0c;覆盖到摄像机的观察视窗。复制一层平面&#xff0c;收窄变成小车两侧的路面&#xff0c;编辑…