播放器重構的探索之路

語言: CN / TW / HK

theme: smartblue

「這是我參與2022首次更文挑戰的第11天,活動詳情查看:2022首次更文挑戰」。

前言:

也許大家也會遇到播放器過於臃腫,播放器控制邏輯複雜度高,業務耦合度高,頁面邏輯分散(跨頁面動畫,續播邏輯)等等這類問題,而這些問題其實歸根結底就是播放器本身沒有“幹(播放器本身)濕(播放器控制)”分離。如果產品中的播放器形態多樣化,那麼在這個播放器中新增某些需求起來也是極其困難,往往牽一髮而動全身。所以需要對播放器進行業務分離,把播放器核心業務以及UI控制層進行抽象化,從而減少相互之間的依賴關係。

播放器重構之路

背景

我所做的項目之前的業務重心一直在社區和社交方面,在視頻日記以及長視頻做了很多嘗試,做了很多差異化的處理,起初的播放器是由一個基礎類,慢慢演變到多個繼承類,而後在產品的優化需求中一直打補丁,加入了很多小功能,比如説:手勢快進,列表滑動播放優化,續播,網絡條件下的自動播放等;項目在起初的時候沒有考慮整體的播放器架構,導致後期播放器的邏輯嚴重依賴頁面,以至於後期的業務變更難以繼續,出現的問題也難以解決。(新人看了不敢亂動,舊人看了一眼,祖傳“屎山”,千萬別動)

探索

在經過足夠耐心的分析之後,在項目中發現了多個層面存在問題: - 播放器的交互部分與業務上的UI耦合在一起,並且多個業務層模塊依賴這個基礎的播放器控制層,往往某一處修改,影響都是成倍的。 - 列表播放時,太多重複性的侵入代碼 - 續播邏輯過於複雜,因為起初的續播方案建立在打補丁的基礎上,所以方案不合理; - 底層播放器的架構存在問題,沒有和業務完全分離;

既然發現了問題,那麼如何去設計播放器模塊的架構呢?或者説什麼樣的架構滿足自身的業務呢?

那麼根據自身的業務需求從而制定了一些必須要滿足的條件:

  • 播放器底層是否需要滿足不容內核的播放器avplayer、ijkplayer或者更多;(需要有統一的播放器適配協議)
  • 播放器控制層是否需要實現差異化的處理;(需要有統一的控制層協議)
  • 播放器列表自動播放的實現方案與業務分離;(需要通過協議的形式或者tableView的分類實現解耦)
  • 播放器手勢統一管理;(手勢合集)

實踐

既然知道了要如何滿足哪些條件,那就放手去做吧。

遵循設計模式的六大原則,我們儘可能將每個類的職責單一化,把底層依賴的模塊抽象化,從而達到上層業務最大的靈活性。

播放器架構

播放器結構

VideoPlayerCenter

VideoPlayerCenter類是中間控制層,它的職責是用來整合所有的模塊,將播放器中的事件(播放器本身的事件、或者主動觸發控制層的事件、或者網絡層面監測的事件等)分發給對應的功能模塊,你可以把它當做一個調度。

以下是VideoPlayerCenter的結構:

播放器的構成.png

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中。後續會繼續完善切換橫豎屏,以及控制層的手勢快進、快退、長按三倍速等相關的功能。