【Android 进阶】仿抖音系列之列表播放视频(三)
在上一篇【Android 进阶】仿抖音系列之列表播放视频(二)中,我们实现列表播放视频,这一篇我们来对其做些优化。
当我们滑动列表播放视频时,如果你设置了状态栏显示网速的话,可以看到网速占用比较大,我们需要实现边播边缓存,下次播放时,就可以从缓存中取,减少网络使用。
Github上已经有现成的缓存库,我们只要集成进来就好,这是链接 AndroidVideoCache
1、创建MyApp 继承 Application,并在AndroidManifest.xml 中注册
2、在MyApplication 中添加代码,可以设置缓存路径、缓存大小等,这里用默认路径,配置缓存大小为1G。
private HttpProxyCacheServer proxy; public static HttpProxyCacheServer getProxy(Context context) { MyApp app = (MyApp) context.getApplicationContext(); return app.proxy == null ? (app.proxy = app.newProxy()) : app.proxy; } private HttpProxyCacheServer newProxy() { return new HttpProxyCacheServer.Builder(this) .maxCacheSize(1024 * 1024 * 1024) // 1 Gb for cache .build(); }
3、在MyVideoPlayer中,重写setUp 方法,添加代码
@Override public void setUp(String url, int screen, Object... objects) { HttpProxyCacheServer proxy = MyApp.getProxy(context); String proxyUrl = proxy.getProxyUrl(url); super.setUp(proxyUrl, screen, objects); }
就在我们以为万事大吉的时候,却发现并没有什么卵用,而且有时播放第二遍的时候还会卡死,这是什么鬼???
于是我们查看了app的缓存目录,发现同一个视频,会缓存多次,所以我们猜想,是不是缓存这里出了问题?
通过查看AndroidVideoCache的源码,我们发现AndroidVideoCache是通过代理的策略实现一个中间层将我们的网络请求转移到本地实现的代理服务器上,这样我们真正请求的数据就会被代理拿到,这样代理一边向本地写入数据,一边根据我们需要的数据看是读网络数据还是读本地缓存数据再提供给我们,真正做到了数据的复用。
更详细的可以查看这篇博客这是链接
我们打断点,查看下AndroidVideoCache返回的url
可以看到同一个视频,2次返回的url 是不一样的,再翻下AndroidVideoCache的源码,我们看到
public Builder(Context context) { this.sourceInfoStorage = SourceInfoStorageFactory.newSourceInfoStorage(context); this.cacheRoot = StorageUtils.getIndividualCacheDirectory(context); this.diskUsage = new TotalSizeLruDiskUsage(DEFAULT_MAX_SIZE); this.fileNameGenerator = new Md5FileNameGenerator(); this.headerInjector = new EmptyHeadersInjector(); }
我们再查看Md5FileNameGenerator的源码
public class Md5FileNameGenerator implements FileNameGenerator { private static final int MAX_EXTENSION_LENGTH = 4; @Override public String generate(String url) { String extension = getExtension(url); String name = ProxyCacheUtils.computeMD5(url); return TextUtils.isEmpty(extension) ? name : name + "." + extension; } private String getExtension(String url) { int dotIndex = url.lastIndexOf('.'); int slashIndex = url.lastIndexOf('/'); return dotIndex != -1 && dotIndex > slashIndex && dotIndex + 2 + MAX_EXTENSION_LENGTH > url.length() ? url.substring(dotIndex + 1, url.length()) : ""; } }
这里我们可以看到,缓存的文件是上面url 进行md5之后的字符串,再加上原来的文件后缀名,这也是为什么缓存目录下同一个视频,会缓存多次的问题。
知道问题出在哪,就好解决了,我们可以对AndroidVideoCache 返回的路径进行截取,只取我们原先的路径,当做缓存的文件名就可以了
public class MyFileNameGenerator implements FileNameGenerator { private static final int MAX_EXTENSION_LENGTH = 4; @Override public String generate(String url) { String extension = getExtension(url); int dotIndex = url.lastIndexOf('.'); if (url.length() > 18 && dotIndex > 18) { return url.substring(dotIndex - 18); } String name = ProxyCacheUtils.computeMD5(url); return TextUtils.isEmpty(extension) ? name : name + "." + extension; } private String getExtension(String url) { int dotIndex = url.lastIndexOf('.'); int slashIndex = url.lastIndexOf('/'); return dotIndex != -1 && dotIndex > slashIndex && dotIndex + 2 + MAX_EXTENSION_LENGTH > url.length() ? url.substring(dotIndex + 1, url.length()) : ""; } }
修改MyApp 中的代码如下
private HttpProxyCacheServer proxy; public static HttpProxyCacheServer getProxy(Context context) { MyApp app = (MyApp) context.getApplicationContext(); return app.proxy == null ? (app.proxy = app.newProxy()) : app.proxy; } private HttpProxyCacheServer newProxy() { return new HttpProxyCacheServer.Builder(this) .maxCacheSize(1024 * 1024 * 1024) // 1 Gb for cache .fileNameGenerator(new MyFileNameGenerator()) .build(); }
到这里,本篇文章也结束了
最后,献上完整代码。Github
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
难得的好文:如何构建一套高可用的 APP 消息推送平台
消息推送作为移动 APP 运营中的一项关键技术,已经被越来越广泛的运用。本文追溯了推送技术的发展历史,剖析了其核心原理,并对推送服务的关键技术进行深入剖析,围绕消息推送时产生的服务不稳定性,消息丢失、延迟,接入复杂性,统计缺失等问题,提供了一整套平台级的高可用消息推送解决方案。实践中,借助于该平台,不仅能提能显著提高消息到达率,还能提高研发效率,并道出了移动开发基础设施的平台化架构思路。 推送基础 移动互联网蓬勃发展的今天,大部分手机 APP 都提供了消息推送功能,如新闻客户端的热点新闻推荐,IM 工具的聊天消息提醒,电商产品促销信息,企业应用的通知和审批流程等等。推送对于提高产品活跃度、提高功能模块使用率、提升用户粘性、提升用户留存率起到了重要作用,作为 APP 运营中一个关键的免费渠道,对消息推送的合理运用能有效促进目标的实现。 推送最早诞生于 Email 中,用于提醒新的消息,而移动互联网时代则更多的运用在了移动客户端程序。要获取服务器的数据,通常有两种方式:第一种是客户端 PULL(拉)方式,即每隔一段时间去服务器获取是否有数据;第二种是服务端 PUSH(推)方式,服务器在有数...
- 下一篇
swift 协议的写时拷贝
其实这只是协议中的一个小的知识点,但是个人觉得这是对协议的一种优化,可以拿来学习一下。 swift的协议概念: OC中也有协议,swift中的协议的作用与OC中基本一样,只是在写法上有一点区别。 我们使用 protocol关键字来定义一个协议。在一个协议中只能存放计算式属性以及方法的声明,而不能对他们进行定义。 协议一般和代理一起使用,协议只是声明一些方法名称和计算式属性,可以认为它就是一种约定,谁遵循了这种约定,谁就实现其中的方法和计算式属性。 关于代理,我们这里不做详述。 首先,我们来看看什么是“写时拷贝”? 写时拷贝 由于协议类型是一种抽象类型,swift在实现它的时候采用了一种十分灵活的机制——写时拷贝。 对于像枚举、结构体这种值类型的对象实例,即便用一个他们所遵循的协议去指向值类型的对象实例, 当协议类型自身或它所指向的对象实例任一方修改了存储式实例属性的值的时候,此时就会发生写时拷贝。 这时,swift会将协议类型对象分配一个新的存储空间,然后将它所指向的值类型的对象实例的当前状态拷贝过去。 概念有些抽象,我们来看看实例吧。 /* 协议是一种比较灵动的动态类型,根据为它所初...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
-
Docker使用Oracle官方镜像安装(12C,18C,19C)
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池
- CentOS8编译安装MySQL8.0.19
- Docker快速安装Oracle11G,搭建oracle11g学习环境
- SpringBoot2配置默认Tomcat设置,开启更多高级功能
- MySQL8.0.19开启GTID主从同步CentOS8
- CentOS7,8上快速安装Gitea,搭建Git服务器
- Jdk安装(Linux,MacOS,Windows),包含三大操作系统的最全安装
- SpringBoot2编写第一个Controller,响应你的http请求并返回结果
推荐阅读
最新文章
- SpringBoot2全家桶,快速入门学习开发网站教程
- SpringBoot2更换Tomcat为Jetty,小型站点的福音
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池
- CentOS8,CentOS7,CentOS6编译安装Redis5.0.7
- MySQL8.0.19开启GTID主从同步CentOS8
- Docker快速安装Oracle11G,搭建oracle11g学习环境
- SpringBoot2整合Redis,开启缓存,提高访问速度
- Windows10,CentOS7,CentOS8安装Nodejs环境
- CentOS7编译安装Cmake3.16.3,解决mysql等软件编译问题
- SpringBoot2编写第一个Controller,响应你的http请求并返回结果