ExoPlayer的缓存 四 缓存Cache 的应用
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
- 基类中定义 各种属性
- 基类中定义 setXXX
- 默认构造函数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 类
- Builder 类中增加 setXXX 函数
- 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
- 继承基类构造函数
- buildUpon 函数 使用 基类构造函数 生成
public class CacheDownloadParameters extends ParametersBase {private CacheDownloadParameters(ParametersBase base) {super(base);}public Builder buildUpon(){return new Builder(this);}
}
ExoPlayer的缓存 四 缓存Cache 的应用相关推荐
- System.Web.Caching.Cache类 缓存 各种缓存依赖
原文:System.Web.Caching.Cache类 缓存 各种缓存依赖 Cache类,是一个用于缓存常用信息的类.HttpRuntime.Cache以及HttpContext.Current.C ...
- zt:缓存一致性(Cache Coherency)入门 cach coherency
http://www.infoq.com/cn/articles/cache-coherency-primer http://www.cnblogs.com/xybaby/p/6641928.html ...
- 浏览器缓存:memory cache、disk cache、强缓存协商缓存等概念
文章目录 分类 memory cache disk cache Service Worker Push Cache 缓存过程 强缓存 1.Expires 2.Cache-Control Expires ...
- 缓存模式(Cache Aside、Read Through、Write Through、Write Behind)
概览 缓存是一个有着更快的查询速度的存储技术,这里的更快是指比起从初始的数据源查询(比如数据库,以下都称作数据库)而言.我们经常会把频繁请求的或是耗时计算的数据缓存起来,在程序收到请求这些数据的时候可 ...
- 缓存之王Caffeine Cache,性能比Guava更强,命中率更高!
点击上方"服务端思维",选择"设为星标" 回复"669"获取独家整理的精选资料集 回复"加群"加入全国服务端高端社群「后 ...
- PHP内容缓存输出 PEAR cache
PHP内容缓存输出 PEAR cache 作者:未知 PEAR cache 安装 /usr/ports/sysutils/pear-Cache make install clean ◆ 内容缓存输出 ...
- Elasticsearch搜索引擎之缓存:Request Cache、Query Cache、Fielddata Cache
ElasticSearch 查询需要占用 CPU.内存资源,在复杂业务场景,会出现慢查询,需要花费大量的时间.为了提高系统的性能,除了增加集群硬件配置这种成本高昂的开销外,还可以使用 ES 的缓存,下 ...
- 读取文件慢_页面缓存(Page Cache)-内存和文件之间的那点事儿(下)
原文:https://manybutfinite.com/post/page-cache-the-affair-between-memory-and-files/ 翻译:RobotCode俱乐部 现在 ...
- Oracle结果集缓存(Result Cache)--服务器、客户端、函数缓存
Oracle结果集缓存(Result Cache)--服务器.客户端.函数缓存 在11g中,Oracle提供了结果集缓存特性.该缓存是在共享内存中存储全部的结果集,如果一个查询SQL被执行,且它对应的 ...
- Nginx使用教程(七):使用Nginx缓存之proxy cache
定义缓存目录 <br\> 使用您喜欢的文本编辑器打开/etc/nginx/nginx.conf,并在http {区域加入: proxy_cache_path /var/www/cache ...
最新文章
- PHP环境下配置WebGrind——让你的网站性能看得见
- 编写工厂类和配置文件
- 提高CocoaPods速度
- 代码+实例:深度学习中的“轴”全解
- 探索性数据分析,这8个流行的 Python可视化工具就够了
- 正则表达式:Pattern 与Matcher
- 【爬虫】beautiful soup笔记(待填坑)
- Memcached常用操作
- Flutter快速上车之Widget
- 绝了!一个 rm -rf 把公司整个数据库删没了
- redis学习-列表(list)常用命令
- nginx负载均衡 加权轮询和ip_hash
- Bootstrap 模态框(Modal)
- Centos 7 keepalived双机热备
- 泰山OFFICE正式在UOS应用商店上架
- python怎么重新运行,如何让python程序重新运行其
- Ubuntu15.10下华南师大锐捷认证客户端的使用详解
- 大厂面试必考的假设检验
- protobuf3 oneof
- Mac电脑使用:删除保存在Mac电脑自带的Safari浏览器、谷歌浏览器、火狐浏览器中的账号和密码的方法