视频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()
    }
}
相关推荐
Sun_gentle3 天前
android studio创建flutter项目
android·flutter·android studio
我命由我123453 天前
在 Android Studio 中,新建 AIDL 文件按钮是灰色
android·ide·android studio·安卓·android jetpack·android-studio·android runtime
我命由我123453 天前
Android 多进程开发 - AIDL 回调、RemoteCallbackList、AIDL 安全校验
android·java·安全·android studio·安卓·android-studio·android runtime
大狗狗5 天前
AndroidStudio开发环境
android studio
L-李俊漩10 天前
Android studio修改gradle路径
android·android studio
周杰伦fans12 天前
Android Studio Git 管理最佳实践
git·elasticsearch·android studio
火焰中舞蹈的小孩13 天前
Unity和Android Studio相互调用 CH340在unity中调用
android·ide·android studio
FunW1n14 天前
Android Studio与Hook模块开发相关问题及实现方案梳理
android·ide·android studio
我命由我1234514 天前
Kotlin 面向对象 - 匿名内部类、匿名内部类简化
android·java·开发语言·java-ee·kotlin·android studio·android jetpack
catchadmin14 天前
“Fatal error: require(): Failed opening required...” 以及如何彻底避免它再次出现
android·ide·android studio