播放器重構的探索之路
theme: smartblue
「這是我參與2022首次更文挑戰的第11天,活動詳情檢視:2022首次更文挑戰」。
前言:
也許大家也會遇到播放器過於臃腫,播放器控制邏輯複雜度高,業務耦合度高,頁面邏輯分散(跨頁面動畫,續播邏輯)等等這類問題,而這些問題其實歸根結底就是播放器本身沒有“幹(播放器本身)溼(播放器控制)”分離。如果產品中的播放器形態多樣化,那麼在這個播放器中新增某些需求起來也是極其困難,往往牽一髮而動全身。所以需要對播放器進行業務分離,把播放器核心業務以及UI控制層進行抽象化,從而減少相互之間的依賴關係。
播放器重構之路
背景
我所做的專案之前的業務重心一直在社群和社交方面,在視訊日記以及長視訊做了很多嘗試,做了很多差異化的處理,起初的播放器是由一個基礎類,慢慢演變到多個繼承類,而後在產品的優化需求中一直打補丁,加入了很多小功能,比如說:手勢快進,列表滑動播放優化,續播,網路條件下的自動播放等;專案在起初的時候沒有考慮整體的播放器架構,導致後期播放器的邏輯嚴重依賴頁面,以至於後期的業務變更難以繼續,出現的問題也難以解決。(新人看了不敢亂動,舊人看了一眼,祖傳“屎山”,千萬別動)
探索
在經過足夠耐心的分析之後,在專案中發現了多個層面存在問題: - 播放器的互動部分與業務上的UI耦合在一起,並且多個業務層模組依賴這個基礎的播放器控制層,往往某一處修改,影響都是成倍的。 - 列表播放時,太多重複性的侵入程式碼 - 續播邏輯過於複雜,因為起初的續播方案建立在打補丁的基礎上,所以方案不合理; - 底層播放器的架構存在問題,沒有和業務完全分離;
既然發現了問題,那麼如何去設計播放器模組的架構呢?或者說什麼樣的架構滿足自身的業務呢?
那麼根據自身的業務需求從而制定了一些必須要滿足的條件:
- 播放器底層是否需要滿足不容核心的播放器
avplayer、ijkplayer
或者更多;(需要有統一的播放器適配協議) - 播放器控制層是否需要實現差異化的處理;(需要有統一的控制層協議)
- 播放器列表自動播放的實現方案與業務分離;(需要通過協議的形式或者tableView的分類實現解耦)
- 播放器手勢統一管理;(手勢合集)
實踐
既然知道了要如何滿足哪些條件,那就放手去做吧。
遵循設計模式的六大原則,我們儘可能將每個類的職責單一化,把底層依賴的模組抽象化,從而達到上層業務最大的靈活性。
播放器架構
VideoPlayerCenter
VideoPlayerCenter
類是中間控制層,它的職責是用來整合所有的模組,將播放器中的事件(播放器本身的事件、或者主動觸發控制層的事件、或者網路層面監測的事件等)分發給對應的功能模組,你可以把它當做一個排程。
以下是VideoPlayerCenter
的結構:
VideoPlayerCenter
會對外開放各個模組的方法來處理,每個新增的模組可以通過新增分類的方式去新增自身的功能實現。
在這個類中,會把各個功能模組組裝,然後根據每個功能模組的回撥觸發到對應的功能模組,比方說:
VideoPlayerPlaybackProtocol
的實現類中有播放器的播放回調,如果觸發該回調之後,會在VideoPlayerCenter
中轉發事件到VideoPlayerControlProtocol
的實現類controlView
中,用於處理播放回調後的控制層UI變更;
VideoPlayerGestureManager
類中有播放器的手勢回撥,如果觸發該回調之後,會在VideoPlayerCenter
中轉發事件到VideoPlayerControlProtocol
的實現類controlView
中,用於處理手勢操作後控制層UI變更;
同樣VideoPlayerNetworkManager
類中也是相同;
VideoPlayerPlaybackProtocol
VideoPlayerPlaybackProtocol
類是播放器的控制層,它的職責是用來抽象播放器,減少外界對播放器的依賴;
這個類會定義播放器的基本屬性,方法,回撥,用於統一播放器的介面,在接入不同的播放器時,只需要實現對應的這套播放器協議即可使用。
VideoPlayerControlProtocol
VideoPlayerControlProtocol
類是播放器的UI控制層,它的職責是用來抽象化UI層的事件,減少外界對播放器的依賴;
VideoPlayerCenter
中的controlView就是這個VideoPlayerControlProtocol
協議的實現類,同時controlView自定義自己的佈局,在頁面切換的時候可以直接通過切換controlView就可以完成播放器的過度。
這個類會定義控制層所有的事件,所有可能會影響到控制層的事件都會通過VideoPlayerCenter
轉發到VideoPlayerControlProtocol
的實現類中。
VideoPlayerGestureManager
VideoPlayerGestureManager
類是播放器控制層的手勢管理,它的職責是管理控制層的手勢;
手勢種類有很多中,可以單擊,雙擊,長按,拖拽等,響應哪一種手勢取決於配置;
VideoPlayerNetworkManager
VideoPlayerGestureManager
類是播放器的網路監測,它的職責是監測網路波動;
每個類的職責劃分是單一的,不會去幹涉其他類的邏輯。通過對控制層的抽象化,解決了控制層差異化的配置,解決了列表播放切換至詳情頁播放的的無縫續播,解決了上層業務對播放器的過度依賴,極大程度的保證了業務層的乾淨整潔。
後續
因為播放器的業務側做了很多減法,目前的這些功能類已經滿足需求。列表自動播放的邏輯是在tableview的分類中(可以複用原來的邏輯),並沒有放在VideoPlayerCenter
中管理,有違最初設計的初心,如果後面要把播放器模組化,可能會有些影響,後面在考慮下是否要把列表播放也放在VideoPlayerCenter
中。後續會繼續完善切換橫豎屏,以及控制層的手勢快進、快退、長按三倍速等相關的功能。
- LeetCode 初級演算法之陣列(上),看看你都學會了嗎?
- LeetCode 初級演算法之連結串列,看看你都學會了嗎?
- LeetCode 初級演算法之字串(上),看看你都學會了嗎?
- 純程式碼佈局,也可以一樣的簡潔
- UIStackView之一問一答
- 使用UIStackView來簡化iOS的介面佈局
- 夏天來了,iOS開發者們該如何減少App耗電?(上)
- 夏天來了,App開發者們如何看待手機發燙問題?
- 聊聊iOS中UITableView複用的那些事
- 曾經經典的微信打飛機遊戲還有人記得嗎?
- iOS 原生渲染與 Flutter 有什麼區別 (上)
- 瞭解 Mach-O檔案
- CocoaPods中podsepc檔案設定詳解
- iOS 原生渲染與 Flutter 有什麼區別 (下)
- 簡單瞭解 iOS CVPixelBuffer (上)
- 談談 iOS 包瘦身方案
- 播放器重構的探索之路
- 如何使用CocoaPods製作私有庫
- iOS 元件化方案