MediaPlayer播放進度條的優化

jopen 8年前發布 | 7K 次閱讀 Android開發 移動開發

原文出處:http://www.jianshu.com/p/56f37988428b 

如何做一個優美、流暢而且準確的播放進度條,也許很多人覺得很簡單,但實際上,這個問題在大部分時間都被忽略了。

計時方式的比較

  • 計時方式――主線程中使用Handler

    -- 這種方式最簡單,在主線程中通過handler.postDealyed(……, 1000),并在onHandleMessage中繼續post消息,這樣就實現了每隔1000ms進行一次消息循環。

  • 計時方式――使用單獨計時線程

    -- 單獨創建一個計時線程,每秒發出time tick事件,主線程通過該事件來更新進度。這種方式比較麻煩,但是不麻煩怎么裝逼呢?

    如何高雅、準確的實現

    對于Handler方式

  • 自身誤差

這種方式下,如果使用handler.postDealyed(……, 1000)方式來進行每秒的計時,是不準確的,是的,有很大誤差,誤差的原因在于在你收到消息,到你重新發出handler.postDealyed的時間,并不是瞬間完成的,這里面有很多邏輯處理的時間,即使沒有邏輯處理的時間,handler本身也是耗損性能的,所以消息并不可能按照理想的1000延遲來進行發送,這就導致了誤差的累積。

  • 線程調度誤差

我們知道,當音樂線程啟動,到handler發出消息,這一段時間內,存在進程調度或者其它邏輯的耗時操作,導致這兩個時間并不是同時發生的。所以,我們每次在post的時候,都需要對計時進行下補償,但是,怎么做呢?

對于Handler方式的優化

我們知道,Android中有很多計時的控件,首先想到的是DigitalClock,結果發現已經廢棄,好吧,看被什么替換了,OK,發現了TextClock,代碼多了不少,感覺更牛逼了。我們直接看他是怎么處理這個問題的:

同樣是通過程序員的嗅覺找到這里:

    private final Runnable mTicker = new Runnable() {
        public void run() {
            onTimeChanged();

            long now = SystemClock.uptimeMillis();
            long next = now + (1000 - now % 1000);

            getHandler().postAtTime(mTicker, next);
        }
    };

哎呦,有點意思,我們之前是通過postDelay來觸發消息事件的,但這里系統使用了postAtTime,這是為什么呢?很自然我們會想到前面兩行代碼,其實也不用想太多,你代個值進去試下就知道了,假如now取出來是1200,那么next = 1200 + (1000 - 1200 % 1000)也就是next= 2000。你看,雖然我們前一次本該在1000觸發的事件,被各種邏輯延遲到1200,那么如果你用postDelay,這個延遲就被累積了,但如果用這種方式,誤差就被補償了。

我們就叫他誤差補償算法吧~

對于單獨計時線程方式

對于單獨計時的線程,由于時間點的觸發事件和主線程已經分開了,計時線程就不會受主線程邏輯的阻塞了,所以,只要保證開始時對起始時間差進行下同步就OK了。

對于單獨計時線程方式的優化

其實對于單獨計時線程來說,已經沒有什么好優化的了,而且優點還能再列舉不少:

  1. 計時邏輯與UI邏輯分離,方便拓展

  2. 計時準確,可以將計時線程封裝,暴露接口,方便拓展

  3. 解耦、裝逼

如果你還要再進一步優化的話,可以在計時的時候,使用時間差的方式來統計,雖然沒什么亂用。


 

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!