ExoPlayer的缓存-- 四 Cache 的使用

文章目录

  • 缓存ID
    • 默认的CacheID
    • 改造后的CacheID
  • 加密文件的处理
    • 缓存下载 DefaultHttpDataSourceFactory
    • CryptoWrapDataSource
  • 文件分片大小
  • 下载网速的计算
  • 下载参数的设置 Builder 设计模式 的使用
    • 定义基类 ParametersBase
    • Builder 类
    • CacheDownloadParameters

缓存ID

默认的CacheID

同一文件 内容服务器 生成的链接有时效性,如果用URL做缓存ID,会出现同一首无法命中缓存的情况。Exoplayer 的缓存默认使用 URL

public static final CacheKeyFactory DEFAULT_CACHE_KEY_FACTORY =(dataSpec) -> dataSpec.key != null ? dataSpec.key : generateKey(dataSpec.uri);

每首歌曲有一个SongID, 如果使用SongID, 每首歌曲的有伴奏 原唱 视频三种文件,也有冲突的可能。

因此使用URL 的path 作为SongID 是比较合适的。

改造后的CacheID

Exoplayer 在创建CacheDataSourceFactory 的时候 传入CacheKeyFactory

        return new CacheDataSourceFactory(cache,new DefaultHttpDataSourceFactory("user-agent"),new FileDataSource.Factory(),new CacheDataSinkFactory(cache, CacheDataSink.DEFAULT_FRAGMENT_SIZE),CacheDataSource.FLAG_IGNORE_CACHE_ON_ERROR, null,new CacheKeyFactory() {@Overridepublic String buildCacheKey(DataSpec dataSpec) {return dataSpec.key != null ? dataSpec.key : dataSpec.uri.getLastPathSegment();}});
}

缓存的时候 生成DownloadRequest 直接使用URL 的path 最为ID参数传入

DownloadRequest request = CacheDownloadManager.buildDownloadRequest(uri.getLastPathSegment(), uri);

加密文件的处理

缓存下载 DefaultHttpDataSourceFactory

K歌播放的文件时加密类型的,在缓存的时候 直接使用DefaultHttpDataSourceFactory 下载流。

因此缓存的文件是加密的。

private static synchronized HttpDataSource.Factory getHttpDataSourceFactory( ) {if (sHttpDataSourceFactory == null) {CookieManager cookieManager = new CookieManager();cookieManager.setCookiePolicy(CookiePolicy.ACCEPT_ORIGINAL_SERVER);CookieHandler.setDefault(cookieManager);sHttpDataSourceFactory = new DefaultHttpDataSourceFactory("user-agent");}return sHttpDataSourceFactory;
}

在播放的时候需要先解密数据,使用 CryptoHttpDataSourceFactory,但是CryptoHttpDataSourceFactory 使用缓存后保存在缓存中的是解密后的数据,播放中导致数据无法识别。

CryptoWrapDataSource

那能不能在播放的时候 送到播放器的数据解密但是下载保存的时候是原始数据呢。Exoplayer 的DataSource 设计使用了装饰模式,参考这个思路,在CacheDataSource 外面再装饰一层解密的CryptoWrapDataSource。 这样Cache 缓存的时候是加密的数据,送到Exoplayer 的CryptoWrapDataSource 是解密以后的数据。

return new ProgressiveMediaSource.Factory(new CryptoWrapDataSource.Factory(buildCacheDataSourceFactory(cache)),.createMediaSource(uri);

文件分片大小

默认的分片大小为5M,CacheDataSink.DEFAULT_FRAGMENT_SIZE

在生成DownloadManager 的时候,传入自定义参数,CacheDataSinkFactory 定义 分片大小。

DownloaderConstructorHelper downloaderConstructorHelper = new DownloaderConstructorHelper(getDownloadCache(context),getHttpDataSourceFactory(),null,new CacheDataSinkFactory(getDownloadCache(context),(sParameters != null && sParameters.mSegmentSize > 0) ? sParameters.mSegmentSize:CacheDataSink.DEFAULT_FRAGMENT_SIZE),null
);DefaultDownloaderFactory downloaderFactory = new DefaultDownloaderFactory(downloaderConstructorHelper);sDownloadManager = new DownloadManager(context,new DefaultDownloadIndex(getDatabaseProvider(context)),downloaderFactory);

下载网速的计算

在Exoplayer 的官方文档中 对下载速度的 需要通过DownloadManager 定期查询。DownloadService 支持Notification 通知,默认实现了一个 ForegroundNotificationUpdater 定期通知 Notification。

下载进度更新不会触发对DownloadManager.Listener. 要更新显示下载进度的 UI 组件,您应该DownloadManager以所需的更新速率定期查询。DownloadService 包含一个示例,它会定期更新服务前台通知。

参考这个实现 实现我们的网速监听。

注册自定义的DownloadManagerListener

mDownloadManagerListener = new DownloadManagerListener(mHandlerListener);
CacheDownloadService.getDownloadManager(mContext).addListener(mDownloadManagerListener);

onDownloadChanged 中监听是否有下载开始,如果有下载开始,开始抛出消息计算网速。

private class DownloadManagerListener implements com.google.android.exoplayer2.offline.DownloadManager.Listener {private Handler mHandler;public DownloadManagerListener(Handler handler){mHandler = handler;}@Overridepublic void onInitialized(com.google.android.exoplayer2.offline.DownloadManager downloadManager) {mDownloadManager = downloadManager;initHandler();}@Overridepublic void onDownloadChanged(com.google.android.exoplayer2.offline.DownloadManager downloadManager, Download download) {if(mHandler != null){if (download.state == Download.STATE_DOWNLOADING) {Message message = Message.obtain();message.what = MSG_START;message.obj = download;if (download.contentLength > 0) {mHandler.sendMessage(message);}} else if (download.state == Download.STATE_COMPLETED) {Message message = Message.obtain();message.what = MSG_FINISH;message.obj = download;mHandler.sendMessage(message);}}}

initHandler() 中 初始化一个线程 用于处理消息和和计算网速

private void initHandler(){mHandlerThreadListener = new HandlerThread("DownloadManagerListener");mHandlerThreadListener.start();mHandlerListener = new Handler(mHandlerThreadListener.getLooper(), new Handler.Callback(){@Overridepublic boolean handleMessage(@NonNull Message msg) {switch (msg.what) {case MSG_START: {Download download = (Download) msg.obj;DownloadInfo downloadInfo = mHashDownloadInfo.get(download.request.id);if (downloadInfo == null) {downloadInfo = new DownloadInfo();downloadInfo.id = download.request.id;downloadInfo.updateTimeMs = download.startTimeMs;downloadInfo.bytesDownloaded = download.getBytesDownloaded();mHashDownloadInfo.put(downloadInfo.id, downloadInfo);}if (!mRunning) {mRunning = true;mHandlerListener.sendEmptyMessage(MSG_UPDATE);}}break;case MSG_UPDATE: {List<Download> downloadList = mDownloadManager.getCurrentDownloads();if (downloadList != null && downloadList.size() > 0) {long nowMs = Clock.DEFAULT.elapsedRealtime();for (Download dl : downloadList) {DownloadInfo downloadInfo = mHashDownloadInfo.get(dl.request.id);long speed = (dl.getBytesDownloaded() - downloadInfo.bytesDownloaded)/ ((nowMs - downloadInfo.updateTimeMs) / 1000);downloadInfo.updateTimeMs = nowMs;downloadInfo.bytesDownloaded = dl.getBytesDownloaded();for (NetworkSpeedListener li : sListener) {li.onProgress(dl, speed, dl.getPercentDownloaded());}}mHandlerListener.sendEmptyMessageDelayed(MSG_UPDATE, 1000);} else {mRunning = false;}}break;case MSG_FINISH:Download download = (Download) msg.obj;DownloadInfo downloadInfo = mHashDownloadInfo.get(download.request.id);long nowMs = Clock.DEFAULT.elapsedRealtime();long speed = (download.getBytesDownloaded() - downloadInfo.bytesDownloaded )/ (nowMs - downloadInfo.updateTimeMs);mHashDownloadInfo.remove(((Download) msg.obj).request.id);for (NetworkSpeedListener li : sListener) {li.onProgress((Download) msg.obj, speed, download.getPercentDownloaded());}break;}return false;}});
}

下载参数的设置 Builder 设计模式 的使用

下载参数的设置使用了 Builder 设计模式

定义基类 ParametersBase

  1. 基类中定义 各种属性
  2. 基类中定义 setXXX
  3. 默认构造函数ParametersBase(ParametersBase base) 这样变量的 赋值 操作都放在 基类中操作,做到统一
class ParametersBase {protected long mMaxCacheSize = 512 * 1025 * 1025;protected long mSegmentSize = mMaxCacheSize;protected String mCachePath;protected int mMaxParallelDownloads;ParametersBase(ParametersBase base){this.mMaxCacheSize = base.mMaxCacheSize;this.mSegmentSize = base.mSegmentSize;this.mCachePath = base.mCachePath;this.mMaxParallelDownloads = base.mMaxParallelDownloads;}ParametersBase() {}......
}

Builder 类

  1. Builder 类中增加 setXXX 函数
  2. build 函数。 build 函数中 直接使用基类构造函数 生成 CacheDownloadParameters
public static class Builder extends ParametersBase{public Builder(){super();}public Builder(ParametersBase base) {super(base);}......public CacheDownloadParameters build(){CacheDownloadParameters parameters =  new CacheDownloadParameters(this);return parameters;}

CacheDownloadParameters

  1. 继承基类构造函数
  2. buildUpon 函数 使用 基类构造函数 生成
public class CacheDownloadParameters extends ParametersBase {private CacheDownloadParameters(ParametersBase base) {super(base);}public Builder buildUpon(){return new Builder(this);}
}

ExoPlayer的缓存 四 缓存Cache 的应用相关推荐

  1. System.Web.Caching.Cache类 缓存 各种缓存依赖

    原文:System.Web.Caching.Cache类 缓存 各种缓存依赖 Cache类,是一个用于缓存常用信息的类.HttpRuntime.Cache以及HttpContext.Current.C ...

  2. zt:缓存一致性(Cache Coherency)入门 cach coherency

    http://www.infoq.com/cn/articles/cache-coherency-primer http://www.cnblogs.com/xybaby/p/6641928.html ...

  3. 浏览器缓存:memory cache、disk cache、强缓存协商缓存等概念

    文章目录 分类 memory cache disk cache Service Worker Push Cache 缓存过程 强缓存 1.Expires 2.Cache-Control Expires ...

  4. 缓存模式(Cache Aside、Read Through、Write Through、Write Behind)

    概览 缓存是一个有着更快的查询速度的存储技术,这里的更快是指比起从初始的数据源查询(比如数据库,以下都称作数据库)而言.我们经常会把频繁请求的或是耗时计算的数据缓存起来,在程序收到请求这些数据的时候可 ...

  5. 缓存之王Caffeine Cache,性能比Guava更强,命中率更高!

    点击上方"服务端思维",选择"设为星标" 回复"669"获取独家整理的精选资料集 回复"加群"加入全国服务端高端社群「后 ...

  6. PHP内容缓存输出 PEAR cache

    PHP内容缓存输出 PEAR cache 作者:未知 PEAR cache 安装 /usr/ports/sysutils/pear-Cache make install clean ◆ 内容缓存输出 ...

  7. Elasticsearch搜索引擎之缓存:Request Cache、Query Cache、Fielddata Cache

    ElasticSearch 查询需要占用 CPU.内存资源,在复杂业务场景,会出现慢查询,需要花费大量的时间.为了提高系统的性能,除了增加集群硬件配置这种成本高昂的开销外,还可以使用 ES 的缓存,下 ...

  8. 读取文件慢_页面缓存(Page Cache)-内存和文件之间的那点事儿(下)

    原文:https://manybutfinite.com/post/page-cache-the-affair-between-memory-and-files/ 翻译:RobotCode俱乐部 现在 ...

  9. Oracle结果集缓存(Result Cache)--服务器、客户端、函数缓存

    Oracle结果集缓存(Result Cache)--服务器.客户端.函数缓存 在11g中,Oracle提供了结果集缓存特性.该缓存是在共享内存中存储全部的结果集,如果一个查询SQL被执行,且它对应的 ...

  10. Nginx使用教程(七):使用Nginx缓存之proxy cache

    定义缓存目录 <br\> 使用您喜欢的文本编辑器打开/etc/nginx/nginx.conf,并在http {区域加入: proxy_cache_path  /var/www/cache ...

最新文章

  1. PHP环境下配置WebGrind——让你的网站性能看得见
  2. 编写工厂类和配置文件
  3. 提高CocoaPods速度
  4. 代码+实例:深度学习中的“轴”全解
  5. 探索性数据分析,这8个流行的 Python可视化工具就够了
  6. 正则表达式:Pattern 与Matcher
  7. 【爬虫】beautiful soup笔记(待填坑)
  8. Memcached常用操作
  9. Flutter快速上车之Widget
  10. 绝了!一个 rm -rf 把公司整个数据库删没了
  11. redis学习-列表(list)常用命令
  12. nginx负载均衡 加权轮询和ip_hash
  13. Bootstrap 模态框(Modal)
  14. Centos 7 keepalived双机热备
  15. 泰山OFFICE正式在UOS应用商店上架
  16. python怎么重新运行,如何让python程序重新运行其
  17. Ubuntu15.10下华南师大锐捷认证客户端的使用详解
  18. 大厂面试必考的假设检验
  19. protobuf3 oneof
  20. Mac电脑使用:删除保存在Mac电脑自带的Safari浏览器、谷歌浏览器、火狐浏览器中的账号和密码的方法

热门文章

  1. 思科交换机配置试题_思科交换机配置命令大全 思科交换机配置手册
  2. 安装永中office 2009个人版 点快捷方式无法运行
  3. 实时高清渲染:Shadows
  4. linux java解压文件怎么打开,java linux 解压zip文件怎么
  5. 计算机毕业设计java+ssm的在线投票管理系统(源码+系统+mysql数据库+Lw文档)
  6. 计算机网络试题及答案(史上最全)
  7. java小游戏程序的编写
  8. arcgis发布路网路径规划服务
  9. 骑士人才linux伪静态,骑士CMS人才系统伪静态的设置方法
  10. 松本行弘为什么开发Ruby