聲明:Socket思想來源于手Q空間團隊,Demo中提供了使用Socket模擬HTTP請求. 本文最初發布在mekor.github.io
我們都知道WebView加載頁面非常緩慢,如果頁面樣式結構比較固定,則可以采用自己的自己封裝的網絡請求去獲取數據,然后拼接成HTML顯示.
優點:
- 通常webview首次加載非常慢,使用Native網絡請求會很快
- 離線包+預加載(靜態HTML、靜態JS、靜態CSS它們的加載、它們離線的東西),首屏進入可直接加載默認數據
缺點:
- 靜態資源包離線下載,不能保證100%
傳統H5加載流程
這里有兩個問題:
WebView的耗時
根據手Q的統計數據,Android的WebView平均打開啟動的速度耗時是0.8秒,有些Android機型基于系統環境可能需要一點多或者兩秒左右;
HTTP協議的網絡層
HTTP有DNS或者建立鏈接的耗時,HTTPS有建立SSL鏈接的耗時。
所以H5通常帶給用戶的體驗是:我點進來不管是怎么時候,是第一次第二次還是第三次,我點進來先等兩秒再說,看兩秒白屏后頁面才可以加載進來,其實這里我們只做了兩個事情去優化首次加載流程:
1. 把WebView啟動和發送請求改成并行
客戶端在啟動WebView的時候同時發起HTML的頁面請求,這里可以實現一個效果:本來我的耗時是T1+T2,現在為T1或T2的最大值,這樣達到并行加載的效果。
當然這里還有一個優化的空間,我們其實已經由客戶端接管了發送網絡請求的事情,以前接管的時候是用HTTP協議,比如像iOS用的是URLSession模塊,但已經讓客戶端接管了,為什么不能夠更大膽一些呢?
2. Socket通道
其實我們可以不拘泥于數據傳輸的方式,所以這里我們把一個HTML的加載從HTTP/HTTPS改造成了一個Socket通道,這是一個App里面長連接的管道,如果手機內部有即時通訊模塊的話,我們是用這個長連接的通道來做HTML的傳輸的,它的作用在于只要你的手機QQ能夠收發消息,你的HTML頁面就能夠加載進來,這樣就達到體驗上的一致性,同時網絡也有比較穩定的提升。
我們基本上做了兩個事情就達到首次進入加速的目的,但后面才是一個關鍵:首次進入我們已經做過優化了,但二次進入怎么去做優化去提高它的顯示速度呢?
本地緩存
Demo簡單介紹
關于加載優化Demo,地址:https://github.com/Mekor/Optimization-of-webView
webView加載耗時問題解決方案簡介:
- 如果有界面變動不大,可以吧HTML直接在本地存放一份,然后從網上請求數據,拼接成HTML,這樣加載速度會很快.這種可以參考用戶版商品的圖片簡介.
- 如果內部動態變化的,但是樣式和交互式規定好的,可以在本地存放一份,當然也可以每次啟動app的時候更新本地存放的靜態資源.這樣的好處就是每次只替換更新的內容.
下面以網易新聞為例,這里我抓包網易新聞的請求,新聞詳情: http://c.m.163.com/nc/article/C0OBRVC7051789DB/full.html
這里我們可以看出,網易新聞也不是直接用webView加載url的方式顯示的.
{
"C0OBRVC7051789DB": {
"body": "<p> 郭德綱的成功除了自身堅持不懈的努力外,當然也因郭德綱遇到了不少“貴人”的幫助,在這其中有一位也是其“貴人”,郭德綱曾經也在很多場合說其是自己的貴人,他就是大鵬。</p><!--IMG#0--><p> 不過,此大鵬非彼大鵬。如今一說到大鵬,都會想到導演電影《煎餅俠》的大鵬,那是趙本山的弟子,卻和郭德綱沒有什么關系。而幫助過郭德綱,使得其相聲在北京能廣受歡迎的大鵬,則是北京文藝廣播《開心茶館》主持人康大鵬。</p><!--IMG#1--><p> 康大鵬作為電臺節目主持人,在沒有聽到郭德綱相聲之前,給聽眾播放的也是一些經典的相聲段子,不過翻來覆去時間長了也令聽眾生厭,久而久之就沒有了興趣。在這種情況下,大鵬聽了郭德綱的相聲后,才感到眼前一亮。</p><!--IMG#2--><p> 當時的郭德綱,雖然在北京也開始站住了腳跟,但是僅限于小部分觀眾知道,并且據說還備受各方打擊,所以才會在相聲中經常有“怨言”。在大鵬看了德云社郭德綱的相聲后,認為這是個機會,德云社也需要聽眾,也需要幫助。</p><!--IMG#3--><p> 于是,大鵬就開始到德云社錄音,然后播放給聽眾聽。這在當時,也是一個不小的舉動。畢竟郭德綱在當時還名不見經傳,而為郭德綱錄音還需要大鵬自己掏腰包購買錄音器材,至于播出后效果如何也擔有一定風險。</p><!--IMG#4--><p> 也正如大鵬所想象,郭德綱的相聲在電臺播出后便反響強烈,使得很多觀眾都開始迷上了相聲,也迷上了郭德綱。在擁有了大批粉絲后,據說郭德綱隨后開辦了一場大型紀念演出,當時有不少電視臺和電臺的領導觀看,而在郭德綱相聲結束后,大鵬還給臺下領導來了一個驚人的一跪。</p><!--IMG#5--><p> 雖然只是單膝點地,但在當時的報紙也給出了驚天一跪的標題,而大鵬的這一跪,也使得郭德綱和電視臺結緣。盡管郭德綱的成名和大鵬有著不可分割的關系,但大鵬還是很謙虛的說兩者是相互的關系,因為節目需要聽眾。</p><!--IMG#6--><p> 在郭德綱進入北京電視臺主持《星夜故事秀》節目時,這也是郭德綱和北京電視臺合作最好的時期,堪稱兩者的“蜜月期”。只是隨著郭德綱的成名,郭德綱后來又轉戰到了天津衛視,自己在北京電視臺的節目則交給了何云偉和李菁來做。</p><!--IMG#7--><p> 這其中的原因,有人說是因為報酬方面產生了分歧,說白了其他電視臺給了更高的價錢。所以北京電視臺才會批郭德綱“忘恩負義”,因北京電視臺為郭德綱的宣傳做了很大的努力,但也有人說是因郭德綱的加盟,才使得北京電視臺節目火了起來。誰是誰非莫衷一是。</p><!--IMG#8--><p> 至于后來,兩者鬧得更是不可開交,直到最后變成了“冤家”。而和北京電視臺鬧分裂后,對原電臺主持人大鵬自然也是有很大的影響,畢竟電視臺和電臺也是一脈相承的關系,不可能不對大鵬產生影響。</p><!--IMG#9--><p> 對與錯是與非都是難以說清,正如大鵬所說,郭德綱的相聲給其節目帶來了聽眾,而電臺也給郭德綱帶去了名氣,兩者也是相輔相成。但不管怎樣,大鵬的確是郭德綱演藝路上的一位“恩人”,起碼讓其早點脫穎而出揚眉吐氣了。</p><p> 特別聲明:本文為網易自媒體平臺“網易號”作者上傳并發布,僅代表該作者觀點。網易僅提供信息發布平臺。</p>",
"users": [],
"replyCount": 1893,
"ydbaike": [],
"link": [],
"shareLink": "http://c.m.163.com/news/a/C0OBRVC7051789DB.html?spss=newsapp&spsw=1",
"votes": [],
"img": [
{
"ref": "<!--IMG#0-->",
"pixel": "400*263",
"alt": "",
"src": "http://dingyue.nosdn.127.net/s9VWjHPwFtTeqKoYJBULaIbs5TmzcYeGFQeljU0IFvZrD1473633706236.jpg"
},
{
"ref": "<!--IMG#1-->",
"pixel": "412*256",
"alt": "",
"src": "http://dingyue.nosdn.127.net/6DXnTuxZs2jvgFJLMW2svrKoh1=KTYXhGwGUH2JlqdpZq1473633736663.jpg"
},
{
"ref": "<!--IMG#2-->",
"pixel": "380*246",
"alt": "",
"src": "http://dingyue.nosdn.127.net/H5jHhCfSD5uhRhMFrHwze4LgrK97qwcG1GkwWGRZcOeqe1473633752645.jpg"
},
{
"ref": "<!--IMG#3-->",
"pixel": "360*286",
"alt": "",
"src": "http://dingyue.nosdn.127.net/udjNFCksz6Fc7fCFAzCBwzUYxWB1TJUVis97X5ZRHpqg61473633775305.jpg"
},
{
"ref": "<!--IMG#4-->",
"pixel": "407*255",
"alt": "",
"src": "http://dingyue.nosdn.127.net/7mbZrlli2D70eS9WHoRmd54RDkr6onqv8Zl1h6V5zJraj1473633824123compressflag.jpg"
},
{
"ref": "<!--IMG#5-->",
"pixel": "400*266",
"alt": "",
"src": "http://dingyue.nosdn.127.net/HVmr=qRm5YReXaRAJBcSaI6WJpMn6DkKHJIVJBdbqMOYY1473633850729compressflag.jpg"
},
{
"ref": "<!--IMG#6-->",
"pixel": "380*232",
"alt": "",
"src": "http://dingyue.nosdn.127.net/HQUW=i7soYmJqlUDaS1iv6pGBI9NzCdFqYU=yC=QT8BDQ1473633896632.jpg"
},
{
"ref": "<!--IMG#7-->",
"pixel": "294*220",
"alt": "",
"src": "http://dingyue.nosdn.127.net/lEs43YivpKRxQqZPlmaIo=SpEOdRTqeYUywHCLqwIqR111473633914904.jpg"
},
{
"ref": "<!--IMG#8-->",
"pixel": "402*238",
"alt": "",
"src": "http://dingyue.nosdn.127.net/bhzvrmx8JUQHVViXI5VKqvHG=c5RIIxx0dssbfTNM7mfE1473633962043.jpg"
},
{
"ref": "<!--IMG#9-->",
"pixel": "329*220",
"alt": "",
"src": "http://dingyue.nosdn.127.net/tN7dLuyOJ0SU3kXoPRrLdXkVMZGJtiS97Qh46opqH2Q0N1473634186617.jpg"
}
],
"digest": "",
"topiclist_news": [],
"dkeys": "null",
"topiclist": [
{
"hasCover": false,
"subnum": "2.8萬",
"alias": "娛樂八卦、影視評論",
"tname": "娛樂大嘴",
"ename": "T1439876075818",
"tid": "T1439876075818",
"cid": "C1374475306828"
}
],
"docid": "C0OBRVC7051789DB",
"picnews": true,
"title": "郭德綱從他的節目走紅 此“貴人”卻不求回報",
"sourceinfo": {
"alias": "娛樂八卦、影視評論",
"ename": "T1439876075818",
"tname": "娛樂大嘴",
"tid": "T1439876075818"
},
"tid": "",
"template": "normal1",
"threadVote": 108,
"askbar": [
{
"title": "主持人",
"headpicurl": "http://dingyue.nosdn.127.net/27vmGgL=A4BbmMAUJIEOEJ2vUlnvIGE9Ufum0roxEDigT1472456332076.jpg",
"alias": " 我是河北交通廣播主持人月色,關于主持、情感和各種天馬行空的問題,問我吧! ",
"expertId": "EX880112773195081120",
"name": "月色",
"concernCount": 6341
}
],
"threadAgainst": 49,
"boboList": [],
"articleTags": "網易號",
"replyBoard": "dy_wemedia_bbs",
"source": "娛樂大嘴",
"huati": [
{
"topicId": "SJ02345751487819348812",
"topicName": "郭德綱"
},
{
"topicId": "SJ1851570047893940154",
"topicName": "趙本山"
}
],
"hasNext": false,
"voicecomment": "off",
"apps": [],
"relative_sys": [
{
"id": "C0RN7O7N00034VR2",
"title": "郭德綱的綜藝版圖:交人脈、捧新人、強化德云IP",
"source": "網易娛樂專稿",
"imgsrc": "http://cms-bucket.nosdn.127.net/a11079eb004f445abdb7146850e4810d20160913141047.jpeg",
"docID": "C0RN7O7N00034VR2",
"from": "HZ",
"type": "doc",
"ptime": "2016-09-13 14:13:21",
"href": ""
},
{
"id": "C0DBP4LV0517ACQ1",
"title": "老梁說天下:郭德綱為什么這么能“惹事兒”",
"source": "縱橫娛樂",
"imgsrc": "http://dingyue.nosdn.127.net/sYo3zfohiqrXHHZIhYV0wqZTpE7RavK7qWneE4BsRH6O=1473265404780compressflag.png",
"docID": "C0DBP4LV0517ACQ1",
"from": "HZ",
"type": "doc",
"ptime": "2016-09-08 00:23:46",
"href": ""
},
{
"id": "C0R1QGIN051789DB",
"title": "唯一被戲稱德云社第一女弟子女星,卻是郭德綱鐵桿粉絲",
"source": "娛樂大嘴",
"imgsrc": "http://dingyue.nosdn.127.net/I=T7AyADVhb6T8KiCoR0Yw0mKqBXyzUNKWyafBy9PRvxF1473724249899.jpg",
"docID": "C0R1QGIN051789DB",
"from": "HZ",
"type": "doc",
"ptime": "2016-09-13 08:01:08",
"href": ""
}
],
"ptime": "2016-09-12 06:59:42"
}
}
我們可以看出, body
里面是配置好的html,同時里面也給出了圖片占位符類似于 ``,通過 img
數組里面的的內容進行替換,img里面提供類似
{
"ref": "<!--IMG#0-->",
"pixel": "400*263",
"alt": "",
"src": "http://dingyue.nosdn.127.net/s9VWjHPwFtTeqKoYJBULaIbs5TmzcYeGFQeljU0IFvZrD1473633706236.jpg"
},
提供了 body
里面的占位符,同時還提供了,pixel,alt,src等.這時我們可以做的事情就多了,根據占位符替換 body
中的占位,通過原生網絡下載圖片等等.Demo中我只做了簡單的HTML拼接.拼接好HTML在把本地的模板添加進去,比如css,js等.最后直接把拼接好的完整的HTML給webView,讓其顯示.具體Demo已經提供了,僅供參考.效果圖:
(僅供參考,css我只是簡單的按照大概寫的,勿噴)
Socket模擬HTTP請求
第二個Demo中模擬了Socket發送HTTP請求的方式,當然我這里只是猜測手Q的實現方式.需要注意的地方就是拼接請求頭.
//拼接http請求
NSString *request = @"GET / HTTP/1.1\n"
"Connection: Close\n"
"Host: m.baidu.com\n"
//告訴服務器客戶端是mac
"User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/40.0.2214.115 Safari/537.36\n\n";