开发者社区> 欢子-3824> 正文
阿里云
为了无法计算的价值
打开APP
阿里云APP内打开

【Android 进阶】仿抖音系列之列表播放视频(三)

简介: 在上一篇【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是通过代理的策略实现一个中间层将我们的网络请求转移到本地实现的代理服务器上,这样我们真正请求的数据就会被代理拿到,这样代理一边向本地写入数据,一边根据我们需要的数据看是读网络数据还是读本地缓存数据再提供给我们,真正做到了数据的复用。

img_d026c1a05c7b5e2512e75739b7249d40.png
image.png

更详细的可以查看这篇博客这是链接

我们打断点,查看下AndroidVideoCache返回的url

img_cfacc4984658ff328ddae593d5e08915.png
image.png

可以看到同一个视频,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

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
Android 进阶的整理
Android 进阶的整理
29 0
【Android开发】 ListView使用实战详解,你get到了嘛?
【Android开发】 ListView使用实战详解,你get到了嘛?
57 0
【Android 应用开发】Android开发技巧--Application, ListView排列,格式化浮点数,string.xml占位符,动态引用图片
【Android 应用开发】Android开发技巧--Application, ListView排列,格式化浮点数,string.xml占位符,动态引用图片
89 0
Android开发之ListView使用经验分享
在Android开发中,ListView是使用最广泛的组件之一,虽然谷歌推出了RecycleView,但是很多项目中依旧在使用ListView,本文将总结一下使用过程中遇到的一些问题,与大家共勉~~~ 一、ListView 与 Adapter List...
760 0
Android开发重要参考资料
=======================博客============================= 秋百万 有心课堂 郭霖 源码 安装ffmpeg 胡凯 官方培训课程 litesuitsway 爱哥 trinea robinRobin Hu...
829 0
+关注
14
文章
0
问答
文章排行榜
最热
最新
相关电子书
更多
低代码开发师(初级)实战教程
立即下载
阿里巴巴DevOps 最佳实践手册
立即下载
冬季实战营第三期:MySQL数据库进阶实战
立即下载