视频feed流框架-原创

背景

目前抖音、快手、其他短剧app遍地都是,但是好用的开源的feed流框架基本没有

于是做了一款可商业化的视频流框架,供大家参考使用,直接上效果

在开源项目:github.com/TimShuai/Vi... 可以查看效果

技术选型

目前市面上视频feed流实现有以下四种方式:

1.ViewPager2和Fragment

优点:方案简单,开发成本低

缺点:fragment创建和销毁有一定的开销,会有明显掉帧情况

2.RecyclerView和PagerSnapHelper

优点:api更灵活,扩展性更强,性能好

缺点:item条目生命周期需要单独控制,需要额外单独处理多指操作和一直滑动情况
3.ViewPager2和RecyclerView.Adapter
优点:性能好,api成熟,多指操作和一直滑动情况兼容好
缺点:item条目生命周期需要单独控制

4.自定义viewpager 成本高,此方案暂不考虑
笔者选择了第三个方案

api使用说明

Feed流:使用ViewPager2实现

Page:TimItemView,条目view,每个itemview上都可以承载n层layer

Layer:layer中加载布局具体的文件

Layout:业务ui控制层,例如播放视频、播放进度等

VideoFeed用不到1000行代码实现了Feed流;有以下优势

  • 架构清晰,每层责任清楚
  • 单一原则,layout负责单一业务,代码简洁、逻辑清晰
  • 耦合度低,各个层级、业务不会产生依赖
  • 性能好,问题少,使用viewpager2性能几乎和RecyclerView差不多
  • 扩展性强,VideoFeed仅仅是帮我们实现Feeds,不关心具体业务
  • 播放器数量,在Video播放layout中,可复用一个播放器或者使用多个播放器,均没有问题

具体使用:
Feed流-viewpager2设置

图层layer

demo中广告层和其他图层是互斥的,demo中根据type进行了判断,例如

广告层 操作面板层 播放层

业务实现层

例如:PlayProgressLayout更新进度的Layout,可以看出它仅仅负责自己单一的进度任务就可以,与其他播放、title等全部是解偶的

kotlin 复制代码
class PlayProgressLayout(val activity: ComponentActivity): IBaseFeedItemLayout(activity) {
    private var progressSeekBar: SeekBar? = null
    private var durationObserver: Observer<Int>? = null
    private var progressObserver: Observer<Int>? = null
    override fun onTimCreateView(type: Int, itemView: View) {
        super.onTimCreateView(type, itemView)
        progressSeekBar = itemView.findViewById<SeekBar?>(R.id.progress_seek)?.apply {
            progress = 0
            max = mainViewModel.videoDuration.value ?: 100
        }
    }
    override fun onTimBindView(position: Int, data: TimData) {
        super.onTimBindView(position, data)
        this.position = position
        this.id = data.id
    }
    override fun onTimSelected() {
        super.onTimSelected()
        if (progressObserver == null) {
            progressObserver = Observer<Int> {
                progressSeekBar?.progress = it
            }
        }
        progressObserver?.let {
            mainViewModel.videoProgress.observe(act, it)
        }
        if (durationObserver == null) {
            durationObserver = Observer<Int> {
                progressSeekBar?.max = it
                Log.d(TAG, "duration = $it")
            }
        }
        durationObserver?.let {
            mainViewModel.videoDuration.observe(act, it)
        }
    }
    override fun onTimDeselected() {
        super.onTimDeselected()
        progressSeekBar?.progress = 0
        removeObserver()
    }
    private fun removeObserver() {
        durationObserver?.let {
            mainViewModel.videoDuration.removeObserver(it)
        }
        progressObserver?.let {
            mainViewModel.videoProgress.removeObserver(it)
        }
    }
    override fun onTimDestroyView() {
        removeObserver()
    }
}
相关推荐
kv1101 天前
Android studio国内开发有关
java·数据库·android studio
烽火聊员2 天前
Android屏幕卡顿traces.txt拉取查看
android·java·android studio
古法安卓2 天前
Android-Ext4文件系统问题排查
android·java·android studio
zihan51811 天前
自己做软件日记9/21 得到了一个良好的文件结构框架
后端·flutter·前端框架·android studio
古法安卓13 天前
Android-休眠唤醒后onLocationChanged没有数据问题排查
android·java·android studio
执明wa15 天前
Android RecyclerView 多类型, 多种 Item
android·xml·开发语言·设计模式·android studio
JMchen15 天前
Android自定义View三大核心流程:measure、layout、draw完全解密
android·android studio
古法安卓16 天前
Android-Fork 机制详解
android·java·android studio
JMchen16 天前
第 12 篇|项目整合与打包发布 —— 从 Demo 到可安装 APK 的完整收官指南
kotlin·android studio
JMchen17 天前
第 9 篇|网络请求基础 —— 从 HttpURLConnection 到 OkHttp
kotlin·android studio