视频在滑动列表中的异步缓存和播放

视频在滑动列表中的异步缓存和播放,转自大量高质量游戏应用源码的众筹论坛php

http://www.zccode.com/forum.php?mod=viewthread&tid=679&extra=git

 

最近在Github上看到VideoPlayerManager这么一个项目,目的在是ListView和RecyclerView中播放小视频,模仿了Instagram中滑动到可见视频项时开始播放该视频,滑动至不可见时中止视频播放的功能github

可是该项目存在几个问题:swift

  1. 快速上下滑动列表后,没法再播放视频,有时还会直接Crash缓存

  2. 不支持网络视频的异步缓存网络

故在该项目的基础上进行了优化,而且支持网络视频的异步缓存框架

网络视频的异步缓存

视频的缓存其实跟图片缓存大体是同样的,如今图片缓存框架不少,可是根本原理都是网络下载+内存缓存+本地缓存这三大块组成。而视频的缓存只须要跳过内存缓存就能够了,当发视频文件未下载时就去下载并本地缓存,下次就直接从本地缓存读取视频文件信息,因此基于图片缓存框架不难实现视频文件的缓存功能。异步

这里我采用了Glide来实现视频缓存,Glide不只支持图片缓存还支持对普通文件缓存,因此使用Glide能够很简单的就能实现视频文件的缓存ide

基于TextureView的视频播放控件

Android原生提供了一个视频播放控件 - VideoView,但VideoView是基于SurfaceView实现的,SurfaceView会单独一个窗口用来绘制,它不在View hierachy中,显示也不受View的属性控制,不能进行平移,缩放等变换,也难以放在ListView或者ScrollView中,一些View中的特性也没法使用。post

为了弥补SurfaceView的不足,Android在4.0中加入了TextureView,它并无建立一个单独的窗口用来绘制,这使得它能够像通常的View同样执行一些变换操做,设置透明度等,也很方便的放在其它ViewGroup中

因此要在ListView或者RecyclerView中播放视频,咱们就须要实现基于TextureView的VideoView,实现代码参考ViewVideo就能够了

视频在滑动列表中的自动播放和中止

要实现视频的自动播放和中止,咱们须要计算每一个item中列表中的可见比。好比当某item可见比大于70%时,则该item视为可见的,激活视频播放。反之视为不可见,中止视频播放

这里简单说下实现原理,主要分为下面三步

  1. 在列表滑动时,判断滑动方向

  2. 根据滑动方向判断相邻的item是否视为可见,好比在下滑列表时,当前可见item的可见比在逐渐减少,而下一项的可见比在逐渐加大,当前item可见比低于70%时中止播放,下一项可见比大于70%时就开始播放

  3. 在快速滑动列表时,不检测item的变化(避免卡顿);在滑动中止时,查找当前可见item中可见比最大的item,若是该item和以前可见的item不同时,则激活该item

列表中视频播放的性能问题

视频的播放主要使用了MediaPlayer,MediaPlayer的状态图以下所示:

state diagramstate diagram

从图中能够看出,视频在开始播放前须要首先经过setDataSource()进行初始化,而后经过prepare()或者prepareAsync()进行播放前准备工做,最后准备完成后经过start()操做才开始播放视频

其中prepare()操做是至关耗时的,这一步操做毫不应该在UI线程中调用,而prepareAsync()则是使用异步的方式调用,因此在list列表中播放视频应该使用prepareAsync()来准备视频

光靠prepareAsync()这一步,可不足以保证list滑动时每帧耗时不超过16ms,像setDataSource(),reset(),release()这些操做都是比较耗时的,虽然达不到引发ANR的程度,可是对于list滑动的流畅性却影响很大

解决方案

这里我采用了将MediaPlayer的所有操做都放在一个单独的线程中去处理,事件回调则经过ui Handler post回ui线程,这样就能够保证list滑动的流畅性

效果预览

代码具体的使用和详细实现方法都已放到Github上

项目地址:VideoListPlayer

欢迎你们拍砖

原文出处:blog.waynell.com

相关文章
相关标签/搜索