這一陣主要做了一下視頻功能送浊。tableView播放視頻在線播放視頻,以及對性能的優(yōu)化栽燕。由于之前只是簡單的搭了一下框架罕袋,隨意扔了兩個(gè)視頻進(jìn)工程,這幾天細(xì)致地做了一下碍岔,只用到了afn框架浴讯,因?yàn)橐郧皼]做過這類的功能,所以沒用SD框架蔼啦,想用自己的代碼實(shí)現(xiàn)一下榆纽。
首先為了不讓視頻界面很low,花了一兩天的時(shí)間捏肢,利用charles抓取其他app的資源奈籽,終于是抓到了可以返回視頻json文件的url。懷著激動(dòng)的心情開始制作鸵赫。
一衣屏、
1.拿到了可以返回視頻信息資源json文件的url,首先就是先將json文件下載下來辩棒,然后再對數(shù)據(jù)進(jìn)行解析狼忱。這里我是使用的afn框架,NSURLSessionDownloadTask來執(zhí)行的下載任務(wù)一睁。代碼如下圖
2.思路首先是將json文件下載到本地钻弄,之后就是解析json文件,文件中有視頻資源url者吁,視頻標(biāo)題窘俺,播放量,占位圖url等好多信息复凳。利用NSJSONSerialization就可以很輕松的將json文件轉(zhuǎn)化為數(shù)組或者字典瘤泪。如圖,我這里是轉(zhuǎn)化為字典染坯,然后將字典逐一存入數(shù)組中均芽。
因?yàn)槭亲淼膉son資源,所以解析的時(shí)候一定要弄清楚json文件的結(jié)構(gòu)層次单鹿,然后再判斷用數(shù)組還是字典來接收數(shù)據(jù)。[]是數(shù)組 {}是字典深纲。
解析拿到數(shù)據(jù)之后仲锄,就可以開始根據(jù)數(shù)據(jù)來制作視頻播放啦劲妙。
3.首先是設(shè)置組數(shù)、行數(shù)儒喊,我設(shè)置的是一組镣奋,行數(shù)是根據(jù)解析拿到數(shù)據(jù)的數(shù)組中,元素的個(gè)數(shù)來動(dòng)態(tài)確定的怀愧。方便之后的刷新侨颈,上拉加載功能,可以動(dòng)態(tài)更改行數(shù)芯义。因?yàn)槟玫降囊粋€(gè)json文件中只有10個(gè)視頻的資源哈垢,所以我的加載方式就是,初始行數(shù)十扛拨,每次拉到底后再繼續(xù)加載十個(gè)視頻耘分。
關(guān)于cell當(dāng)然是要自定義了,因?yàn)橐シ乓曨l绑警,還要顯示標(biāo)題之類的數(shù)據(jù)求泰。自定義cell就不在這里總結(jié)了,搞好布局就好了计盒。重點(diǎn)就是加載視頻的問題了渴频,因?yàn)槭堑谝淮危杏X還是很麻煩的北启,整體做過一次之后卜朗,就有了明確的思路。
4.重頭戲就在cellForRowAtIndexPath方法中了暖庄,注意聊替,視頻播放一定要利用cell的重用機(jī)制。開寫培廓!
剛開始寫的時(shí)候惹悄,就是簡單的從數(shù)組中取出模型,然后給cell上的player賦上url肩钠;然后簡單的處理了一下播放邏輯泣港。感覺還不錯(cuò)。但是當(dāng)我開始使用MJRefresh框架制作上拉价匠、下拉刷新加載功能的時(shí)候就出大問題了当纱。
初始數(shù)據(jù)只有十條,很少的數(shù)據(jù)下是看不出什么的踩窖。當(dāng)加載到20-30個(gè)視頻的時(shí)候坡氯,我發(fā)現(xiàn)簡直是卡死了!!箫柳!界面掉幀極其嚴(yán)重手形,甚至?xí)ㄋ烂趸小W聊チ讼拢耶?dāng)前的思路是涮毫,每當(dāng)一個(gè)cell要出現(xiàn)在視野中的時(shí)候,就給他添加一個(gè)播放器罢防,初始化播放器的時(shí)候艘虎,將視頻的url賦上去。所以就導(dǎo)致顷帖,每次cell要出現(xiàn)的時(shí)候,都要先下載視頻贬墩,下載好了cell才會(huì)滾到視野,下一個(gè)cell又是這樣妄呕,界面總是會(huì)卡住四五秒陶舞,視頻下載完才會(huì)再滾一下。
解決方法:界面卡頓就是因?yàn)橄螺d任務(wù)阻塞了主線程绪励,所以要開子線程,在子線程中進(jìn)行下載任務(wù)停做。然后等待下載任務(wù)完成大莫,刷新一下UI界面就可以了。(還是太天真了)
之后發(fā)現(xiàn)即使多線程下載了只厘,界面依舊是超級(jí)卡,因?yàn)槊看紊舷聺L動(dòng)cell的時(shí)候都要開線程進(jìn)行下載任務(wù)羔味,滾的越多越快,下載任務(wù)越重忘蟹,還是會(huì)越來越卡。
主要原因:1.沒有做圖片緩存的原因寒瓦。滾動(dòng)cell會(huì)一直從網(wǎng)絡(luò)上獲取圖片坪仇。 ? 2.下載任務(wù)重復(fù),來回滾動(dòng)的時(shí)候喂很,一個(gè)cell 滾到視野-》劃出視野-〉重新進(jìn)入視野皆刺,即便是一個(gè)cell,出現(xiàn)在視野中兩次羡蛾,也要執(zhí)行兩次同樣的下載任務(wù)。任務(wù)繁重忙干。
于是開始使用緩存機(jī)制!三級(jí)緩存浪藻,緩存,本地爱葵,網(wǎng)絡(luò)。將下載過的數(shù)據(jù)存儲(chǔ)到緩存中赞哗,寫到本地文件中辆雾,當(dāng)再次滑到的時(shí)候,就直接從本地加載或者讀取緩存涂乌,cpu的負(fù)擔(dān)會(huì)小很多英岭。如下圖
首先先創(chuàng)建以下三個(gè)引用,由于網(wǎng)絡(luò)請求數(shù)據(jù)诅妹,要考慮到網(wǎng)絡(luò)問題毅人,于是在視頻數(shù)據(jù)沒下載加載完時(shí)尖殃,在播放器上方先顯示占位圖片。
operationDict用于裝載NSOperation缔俄,當(dāng)有下載任務(wù)時(shí)器躏,就將有下載任務(wù)的operation以鍵值的方式存入字典中,當(dāng)下載完成時(shí)登失,再將其從字典中移除,我這里用的展位圖片的url作為鍵状婶,operation作為值存入馅巷。這樣還有一個(gè)好處就是,我們可以通過鍵的對比令杈,過濾掉重復(fù)的下載任務(wù)逗噩,因?yàn)橄螺d任務(wù)的url是唯一的,當(dāng)有下載任務(wù)的時(shí)候异雁,先判斷字典中有沒有相同的,有就不執(zhí)行下載任務(wù)项炼,沒有就添加進(jìn)去示绊,開始下載。
imageCache就是圖片緩存面褐,將下載好的占位圖,以鍵值存入數(shù)組湃窍,再次使用的時(shí)候讀取緩存就好了,道理一樣您市,沒有的就存進(jìn)字典,有的就不存薪棒。
三級(jí)緩存思路就是泽篮,1.當(dāng)滑動(dòng)到cell時(shí),根據(jù)cell的indexPath拿到模型中保存的url,然后根據(jù)url去本地緩存(上面介紹的字典)查找,有數(shù)據(jù)的話就直接使用亏拉;2.沒有的話逆巍,再去本地文件中查找;有的話就使用锐极,3.沒有的話再根據(jù)url去網(wǎng)上獲取下載。
下載下來之后肋层,先根據(jù)鍵值判斷緩存翎迁、本地中有沒有該數(shù)據(jù),有的話就不存汪榔,如果沒有的話就存入緩存,寫入本地沙盒雌团,以后就不用下載了士聪。節(jié)省了大量cpu資源,也為用戶節(jié)省了大量的流量戚嗅。具體實(shí)現(xiàn)看代碼:
完成了這些操作替久,本以為大功告成,但是真機(jī)運(yùn)行一下蚯根,發(fā)現(xiàn)是比之前好了很多,但是依舊是卡蒂誉,掉幀隨著數(shù)據(jù)量的增多越來越嚴(yán)重距帅。
一輪思考時(shí)候,我發(fā)現(xiàn)既然有了占位圖碌秸,那么干脆直接就不要給出現(xiàn)在視野的cell添加視頻播放器,不給他視頻url蹂窖,當(dāng)用戶點(diǎn)擊視頻的播放按鈕的時(shí)候恩敌,再動(dòng)態(tài)的為那一行cell添加視頻播放器,加載url纠炮,這不就相當(dāng)于每個(gè)cell剛開始的時(shí)候就僅僅加載一個(gè)本地的占位圖嗎!Jǘ贰弧蝇!佩服自己!I尘A椒肌(肯定有人早就知道了,但是我就是想得瑟下)怖辆,當(dāng)用戶不想看這行cell的視頻删顶,將它滾出視野之外的時(shí)候淑廊,我們再將cell的播放器釋放掉,只在用戶點(diǎn)擊播放的時(shí)候繼續(xù)創(chuàng)建加載录粱。免去了滑動(dòng)cell時(shí)的大量加載画拾,再也不卡頓,絲滑流暢青抛。