美文网首页安卓开发Android精选
【Android 进阶】仿抖音系列之列表播放视频(三)

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

作者: 欢子3824 | 来源:发表于2018-10-18 10:31 被阅读776次

    前言

    上一篇,我们实现了列表播放视频,这一篇我们来对其做些优化。

    问题

    当我们滑动列表播放视频时,如果你设置了状态栏显示网速的话,可以看到网速占用比较大,我们需要实现边播边缓存,下次播放时,就可以从缓存中取,减少网络使用。

    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) {
           if (url.startsWith("http")) {
                HttpProxyCacheServer proxy = MyApp.getProxy(context);
                String proxyUrl = proxy.getProxyUrl(url);
                super.setUp(proxyUrl, screen, objects);
            } else {
                super.setUp(url, screen, objects);
            }
        }
    

    就在我们以为万事大吉的时候,却发现并没有什么卵用,而且有时播放第二遍的时候还会卡死,这是什么鬼???

    于是我们查看了app的缓存目录,发现同一个视频,会缓存多次,所以我们猜想,是不是缓存这里出了问题?

    通过查看AndroidVideoCache的源码,我们发现AndroidVideoCache是通过代理的策略实现一个中间层将我们的网络请求转移到本地实现的代理服务器上,这样我们真正请求的数据就会被代理拿到,这样代理一边向本地写入数据,一边根据我们需要的数据看是读网络数据还是读本地缓存数据再提供给我们,真正做到了数据的复用。


    image.png

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

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


    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 进阶】仿抖音系列之列表播放视频(三)

        本文链接:https://www.haomeiwen.com/subject/yljjzftx.html