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