如何從新架構 JPVideoPlayer

注意:此文爲配合 JPVideoPlayer version 2.0 版本發佈而寫,若是你想了解 2.0 版本的更新內容和全部實現細節,請點擊前往 GitHub

導言:我幾個月前寫了一個在 UITableView 中滑動 UITableViewCell 播放視頻的框架,相似於「新浪微博」 和 「Facebook」 首頁視頻播放。我也爲初版本的 JPVideoPlayer 實現寫了兩篇文章:
0一、[iOS]仿微博視頻邊下邊播之封裝播放器 講述如何封裝一個實現了邊下邊播而且緩存的視頻播放器。
0二、[iOS]仿微博視頻邊下邊播之滑動TableView自動播放 講述如何實如今UITableView中滑動播放視頻,而且是流暢,不阻塞線程,沒有任何卡頓的實現滑動播放視頻。同時也將講述當UITableView滾動時,以什麼樣的策略,來肯定究竟哪個cell應該播放視頻。

當時匆忙實現功能,沒有仔細斟酌架構的問題,也沒有完全的實現單個功能的組件化。並且因爲架構設計不足帶來一些不可避免的問題。這些問題,1.0 版本的用戶應該有所體會。前段時間獨自回了一趟老家,車程比較長,並且能夠專一而不被打擾,在車上寫了一個 2.0 版本。2.0 版本有部份內容模仿了SDWebImage 的設計。html

2.x 版本效果以下:

01.JPVideoPlayer Version 2.0 如何使用?

考慮到 API 和架構都從新設計了,尤爲是 API 所有從新設計,1.0 版本的 API 已經不能沿用了,機智的我已經作好了被罵得很慘的心理準備了。git

若是你是新的用戶,就不會受以前版本的影響。最終無論你是新用戶仍是老用戶,你必定會喜歡這種新的 API 設計的,由於這是目前 iOS 最受歡迎的 API 設計。github

Objective-C:

#import <UIView+WebVideoCache.h>

...
NSURL *url = [NSURL URLWithString:@"http://lavaweb-10015286.video.myqcloud.com/%E5%B0%BD%E6%83%85LAVA.mp4"];
[aview jp_playVideoWithURL:url];
複製代碼

02.JPVideoPlayer Version 2.0 內部運行細節?

不少用戶可能不會有時間去讀源碼,可是也許會關心 2.0 版本內部實現的一些大的方式,因此這裏我總結了一張 2.0 版本的實現大體結構圖表,以下:web

下面我用文字來表述一下框架內部的運做順序:緩存

  • 01.提供給外部調用的 API 很是簡潔,採用爲 UIView 添加分類方法的形式爲外界調用,只要導入了頭文件,全部 UIView 的子類都擁有播放視頻的方法。框架把 UIView 的分類方法做爲和框架內部交互的橋樑。安全

  • 02.JPVideoPlayerManager 負責甄別用戶傳過來的 URL,根據不一樣的 URL 做出不一樣的反應進行視頻播放。具體細節以下:微信

  • 02.一、是不是本地文件路徑,若是是本地路徑,直接把路徑給負責視頻播放的工具類 JPVideoPlayerPlayVideoTool 進行視頻播放;網絡

  • 02.二、若是不是本地路徑,再根據 URL 生成緩存的 key 給 JPVideoPlayerCache 工具類查找是否有本地緩存文件,若是有緩存就把緩存路徑返還給JPVideoPlayerManagerJPVideoPlayerManager 會把路徑給負責視頻播放的工具類 JPVideoPlayerPlayVideoTool 進行視頻播放;架構

  • 02.三、若是沒有本地緩存,就把 URL 給 JPVideoPlayerDownloader 下載工具類,這個工具類就會去網絡上下載視頻數據,每下載完一段數據,都會返回給 JPVideoPlayerManagerJPVideoPlayerManager 會先把這段數據給 JPVideoPlayerCacheJPVideoPlayerCache 先把數據緩存到磁盤,而後再把緩存的路徑返還給JPVideoPlayerManagerJPVideoPlayerManager 會把路徑給負責視頻播放的工具類 JPVideoPlayerPlayVideoTool 進行視頻播放。框架

03. JPVideoPlayer Version 2.0 更新了哪些內容?

類名 功能點
JPVideoPlayerDownloaderOperation 下載單個視頻文件工具
JPVideoPlayerDownloader 下載工具類,管理下載操做隊列
JPVideoPlayerCachePathTool 管理臨時和完整視頻存儲路徑
JPVideoPlayerCacheConfig 緩存配置文件,包括緩存週期,最大磁盤緩存等
JPVideoPlayerCache 緩存工具類,負責視頻數據的存、取、刪、更新
JPVideoPlayerResourceLoader 視頻播放器的數據代理,負責將網絡視頻數據填充給播放器
JPVideoPlayerPlayVideoTool 視頻播放工具類
JPVideoPlayerManager 管理者,協調各個模塊相互配合工做

接下來我將大體描述一下每一個類的實現:

  • 01.JPVideoPlayerDownloaderOperation:它繼承自 NSOperation,它內部持有一個 NSURLSession 實例對象,由這個實例對象去負責下載視頻數據,JPVideoPlayerDownloaderOperation 成爲這個實例對象的代理,監聽獲取下載到的數據,並將得到的數據回傳給操做的全部者 JPVideoPlayerDownloader

  • 02.JPVideoPlayerDownloader:它持有一個下載隊列,下載隊列裏存放的是 JPVideoPlayerDownloaderOperation 實例對象。考慮到播放視頻數據量較大並且是持續的,爲了將全部的網絡資源用於加載當前用戶播放的視頻,提高使用體驗,因此這個隊列在任什麼時候候都只容許一個下載操做運行。它接收到 JPVideoPlayerDownloaderOperation 回調的數據之後會繼續把數據回傳出去。

  • 03.JPVideoPlayerCachePathTool:它負責管理緩存文件的路徑,包括臨時和完整視頻存儲路徑兩個部分。

  • 04.JPVideoPlayerCacheConfig:這個類存放着緩存存儲週期,最大磁盤緩存等緩存配置數據。

  • 05.JPVideoPlayerCache:它負責數據的存、取、刪、更新等功能。當調用存數據的功能時,會在臨時文件存放的文件夾內新建一個 mp4 文件,並開始將數據寫入到這個文件內,存完一段數據之後,會將存儲數據的路徑回調出去。每次播放視頻的時候,都會去查詢緩存中有沒有這個 URL 的完整數據緩存,若是有就會把路徑回調出去。它還對外提供獲取緩存大小的功能,若是你須要在設置裏獲取當前視頻緩存,能夠調用這個接口。它還有刪除緩存視頻數據的功能。

  • 06.JPVideoPlayerResourceLoader 這個類沿用自 1.0 版本,負責從已經下載的數據中找出播放器須要的數據,並將數據填充到播放器的數據請求中進行視頻播放。

  • 07.JPVideoPlayerPlayVideoTool 這個類持有一個視頻播放器,負責串聯從視頻數據到圖像和影音的整個播放功能。

  • 08.JPVideoPlayerManager 它是框架的管理者、大管家,它的具體功能上面「內部細節」已經陳述過了,這裏不重複了。

  • 09.其餘還有一個數據加載進度條和一個緩衝狀態指示器,這些都很簡單。還有就是 2.0 版本的 Demo 將 UITableViewController 視頻播放抽到一個分類中集中管理,也方便後期維護,若是你的需求和 Demo 相似,能夠考慮直接把這個分類拽進項目,須要改動的代碼不多,就能實現。

04.爲何要這麼改?

這個問題我想從用戶和我本身,還有它原本應該是什麼樣子這些維度來分析。

04.一、用戶角度
  • 01.首先,受用戶歡迎的框架應該要具有兩個基本的素質。第一,調用起來方便,能一行代碼解決的,毫不搞兩行。第二,不侵入用戶的項目,萬一哪天框架不維護了,也不要成爲用戶的累贅。

  • 02.其次,我說一個我今天看一個框架的感覺,是一個相似微信選擇多張照片的框架,框架對外提供的接口不夠我用,因此我只能去框架內部改,可是當我找一個功能的時候,框架文檔沒有說明,我在那些代碼應該放的位置也沒有找到,需求就是改字體和顏色,我找了一上午,終於在一個不可能猜到的位置找到了那幾行代碼。這裏就有幾個問題點:

  • 咱們對外提供的接口儘可能讓使用者夠用,若是沒有考慮到,那用戶就可能會來框架裏改。
  • 咱們的框架類的命名,方法的命名都應該遵照蘋果的那套標準,由於你們每天在用的都是蘋果 API,若是徹底不遵照蘋果那套,那用戶來到框架裏就是一頭霧水,這裏有一個溝通成本的問題,看懂代碼以前還要先熟悉咱們特有的標準。就像去美國,要和美國人說話,要先學英語。
  • 文檔必定要詳實,每一個人水平都不同,代碼可能看不懂,可是文字誰都認識,這是做者和用戶溝通的基礎。
04.二、做者角度

維護框架其實也是很花時間的一件事情,1.0 版本的時候,就常常有用戶給我留言,發QQ消息和我溝通實現的細節,還要他們但願下個版本但願加進去的一些功能。

當時不少功能的代碼都混在一個類裏,第一就是這個類上千行代碼,我本身要改一個東西都須要用搜索功能才能找到,各個方法之間相互調用的時候跳來跳去,頭暈眼花。

如今每一個模塊劃分完功能之後,每一個功能的核心代碼都高度集中在對應的類裏,隱藏實現的細節,屏蔽了外部的干擾,只對外提供必要的接口。如今調試問題的時候,分析到出現問題可能的模塊之後,能快速定位到對應類的對應方法裏,只須要在當前類裏專一當前的問題就能夠了,不須要考慮外部的影響。這個效率的提高仍是蠻明顯的。

因此從做者的角度,這個架構的好處就是,第一,方便我後期的維護,提升效率;第二,方便和用戶的溝通,減小溝通成本;第三,當有新功能的時候,我能快速的把代碼寫到對應的類別裏。

04.三、它原本的樣子

前段時間看 BBC 的 「Planet Earth」 紀錄片,裏面說螞蟻巢穴裏有幾千萬只螞蟻,可是卻分工明確,秩序盡然。原來,螞蟻分爲四類:

  • 蟻后,也叫蟻皇,是一族之主,專管產卵繁殖,通常一羣只有一個,體型特大,行動不便,由工蟻侍候。
  • 雄蟻,專與蟻后交配,交配後即死亡,一羣中有數十隻或數百隻,要看蟻羣的大小。
  • 工蟻,是蟻羣中的主要成員,專司覓食、飼養幼蟻、侍候蟻后、搬家清掃等等雜勤工做。
  • 兵蟻,個頭較大,雙顎發達,是蟻羣中的保衛者,擔負着本蟻羣的安全,若有外蟻入侵,或爭奪食物時,必誓死決鬥。

咱們的代碼或許也能夠仿照大天然,先劃分功能,再列出幾個類,將功能點挨個集中到類裏,武裝出類,就是所謂的對象。這就是我理解的框架應該有的美。

05.Update.

2017.04.04 更新.

2017.05.31 更新:

2017.05.02 更新. 有些朋友反應有些視頻沒法邊下邊播, 具體解決思路請參考 這篇博文

NewPan 的文章集合

下面這個連接是我全部文章的一個集合目錄。這些文章凡是涉及實現的,每篇文章中都有 Github 地址,Github 上都有源碼。

NewPan 的文章集合索引

若是你有問題,除了在文章最後留言,還能夠在微博 @盼盼_HKbuy 上給我留言,以及訪問個人 Github

相關文章
相關標籤/搜索