随笔 - 632  文章 - 17  评论 - 54  阅读 - 93万

AndroidVideoCache实现预缓存

一、概述

  案例:实现一个视频预缓存的需求

  原理:

    1.本地有缓存就优先播放缓存,本地没有缓存就从服务端拉取数据存入缓存,然后再读取缓存播放

    2.要实现1中描述的功能,a.首先要再App中新建一个代理服务 b.客户端请求代理服务 c.代理服务收到客户端请求,开启一个线程A发起请求网络服务器,d.将线程A中获取到的数据写入本地缓存 e.客户端从本地缓存中读取数据并播放。

    

 

   使用到的技术及框架:

      1.本例是在上一篇文章中使用到的AndroidVideoCache框架的基础上进行改造的。

      2.主要是加入了预缓存的功能PreLoadManager

  源代码下载:

  AndroidVideoCache_PreCache

二、代码示例

  1.新建一个单例类PreLoadManager

1
PreloadManager

  2.在PreLoadManager类中定一个Map用来存储所有的任务,其中key为url ,value为具体的任务

1
2
3
4
/**
    * 保存正在预加载的{@link PreloadTask}
    */
   private LinkedHashMap<String, PreloadTask> mPreloadTasks = new LinkedHashMap<>();

  3.添加一个任务到任务池子中

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/**
     * 开始预加载
     *
     * @param rawUrl 原始视频地址
     */
    public void addPreloadTask(String rawUrl, int position) {
        if (isPreloaded(rawUrl)) return;
        PreloadTask task = new PreloadTask();
        task.mRawUrl = rawUrl;
        task.mPosition = position;
        task.mCacheServer = mHttpProxyCacheServer;
        Log.i(TAG, "addPreloadTask: " + position);
        mPreloadTasks.put(rawUrl, task);
 
        if (mIsStartPreload) {
            //开始预加载
//            Log.i(TAG,"开始预加载: " + position);
            task.executeOn(mExecutorService);
        }
    }

  通过task.executeOn(mExecutorService)方法就立即开始执行任务,其执行的核心代码如下所示:

复制代码
 /**
     * 开始预加载
     */
    private void start() {
        Log.i(TAG,"开始预加载:" + mPosition);
        HttpURLConnection connection = null;
        try {
            //获取HttpProxyCacheServer的代理地址
            String proxyUrl = mCacheServer.getProxyUrl(mRawUrl);
            Log.e("预加载的路径:",proxyUrl);
            URL url = new URL(proxyUrl);
            connection = (HttpURLConnection) url.openConnection();
            connection.setConnectTimeout(10000);
            connection.setReadTimeout(10000);
            InputStream in = new BufferedInputStream(connection.getInputStream());
            int length;
            int read = -1;
            byte[] bytes = new byte[8 * 1024];
            while ((length = in.read(bytes)) != -1) {
                read += length;
                //预加载完成或者取消预加载
                if (mIsCanceled || read >= PreloadManager.PRELOAD_LENGTH) {
                    Log.i(TAG,"结束预加载:" + mPosition);
                    break;
                }
            }
            if (read == -1) { //这种情况一般是预加载出错了,删掉缓存
                Log.i(TAG,"预加载失败:" +  mPosition);
                File cacheFile = mCacheServer.getCacheFile(mRawUrl);
                if (cacheFile.exists()) {
                    cacheFile.delete();
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            Log.i(TAG,"异常结束预加载:" + mPosition+"|"+e.getMessage()+"\n"+mCacheServer.getProxyUrl(mRawUrl));
        } finally {
            if (connection != null) {
                connection.disconnect();
            }
        }
    }
复制代码

  其本质上就是模拟了一个客户端发起了一个网络请求,当这个网络请求获取到的数据包的到校>=512kb的时候立马终止线程。客户端线程终止后最终会调用HttpProxyCacheServerClients的finishProcessRequest()方法,同时停止真正下载数据的线程。

  4.取消任务

复制代码
  /**
     * 停止所有的预缓存任务
     */
    public void stopAllPreloadTask() {
        Iterator<Map.Entry<String, PreloadTask>> iterator = mPreloadTasks.entrySet().iterator();
        while (iterator.hasNext()) {
            Map.Entry<String, PreloadTask> next = iterator.next();
            PreloadTask task = next.getValue();
            task.cancel();
        }
    }
复制代码

  5.设置预缓存的大小

1
2
3
4
/**
    * 预加载的大小,每个视频预加载512KB,这个参数可根据实际情况调整
    */
   public static final int PRELOAD_LENGTH = 1024 * 1024 * 1;

  

posted on   飘杨......  阅读(1199)  评论(0编辑  收藏  举报
编辑推荐:
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
阅读排行:
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
历史上的今天:
2013-12-08 使用Android绘图技术绘制一个椭圆形,然后通过触摸事件让该椭圆形跟着手指移动
2013-12-08 Android解决自定义View获取不到焦点的情况
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

点击右上角即可分享
微信分享提示