AndroidVideoCache实现预缓存


一、概述

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

  原理:

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

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

    

 

   使用到的技术及框架:

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

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

  源代码下载:

  AndroidVideoCache_PreCache

二、代码示例

  1.新建一个单例类PreLoadManager

PreloadManager

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

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

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

 /**
     * 开始预加载
     *
     * @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.设置预缓存的大小

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

  


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM