WebView(網絡視圖)能加載顯示網頁,可以將其視為一個瀏覽器。
在Android手機中,網頁的解析和顯示網頁的能力是由webkit內核實現的。
(如chrome瀏覽器使用的是webkit內核,現在,webkit被內置到了android系統中)
webview對網頁處理也是交給強大的webkit做的
webview在android SDK(原生)中:
封裝為一個叫做WebView組件,通過這個組件可以在app中顯示html+css+js,當然也就可以顯示一個遠程url,比如用它打開百度首頁是可以的。
可以理解為:android開發中的一個activity里使用了webview組件,並打開了一個html頁面呈現給用戶。
其中“activity”是android原生開發時的“一張頁面”,app的所謂跳轉到不同“頁”是在activity中跳來跳去,activity是java的一個類,布局則是使用xml(如果沒做過原生android開發就這么理解就行)
webview在mui app框架開發中:
在mui開發中,這些webview就是一張一張的網頁。
這些網頁是webview對象,其操作方法被封裝在html5+的plus.webview對象中
webview本身只是個瀏覽器效果組件,切換即使網頁之間的跳轉,理論上不可能像原生的activity中切換一樣流暢,本身也不會有什么動畫。
還好,mui的開發組,dcloud(數字天堂)和他們的html5+中國產業聯盟(社區)實現了webview切換的動畫效果,他們把這些webview映射到了真正的java webview,調用的也是原生的activity切換動畫,從而使得webview切換也可以像原生app activity一樣切換的效果!
關於dcloud的html5+和native.js技術請看我另一篇博客: http://www.cnblogs.com/devilyouwei/p/6793609.html
關於原生android webview這個組件使用的博客:http://www.jianshu.com/p/d2f5ae6b4927
簡約圖:
原生開發和mui的hybrid模式區別圖:
先來談談我對mui的webview的理解:
使用mui開發的app,其實是在做web前端開發,打開的webview是網頁,用js+html+css替代了原來的xml+java activity的傳統android開發模式,h5最終性能相對原生一定是降低了很多(主要原因不在webkit的解析速度,而是最終所有的ui和業務邏輯還是會轉化為android sdk交由java去實現,google可沒有直接提供android的js開發接口,mui的dcloud則是采用了native.js來提供js開發接口(js映射為原生代碼)
我們按照傳統網頁的方式去理解:
將app理解為瀏覽器,將webview理解為瀏覽器下不同標簽tab,每一個tab也是一個不同的頁面,瀏覽器瀏覽可以在tab之中切換,以此來實現app不同webview(頁面)的切換
場景一:
在mainfest.json中我們配置的首頁,比如login.html,然后我們啟動app,login.html將會第一個呈現在我們屏幕上,這就是第一個tab標簽(稱之為launchWebView),如果此時我們關閉這個tab,那么瀏覽器沒有其他tab將會關閉。
app也是一個道理,只有一個webView的情況下(假設就是launchWebView,首頁),將會退出,可以在首頁login.html使用plus.webview.getLaunchWebView().close()測試,app將會直接退出!
(在原生的android開發中,如果只有一個activity的時候關閉當前activity也會退出app,其實webview之於html5 app,相較於,activity之於android app,邏輯處理十分相似^_^)
場景二:
瀏覽器已經有了首頁的tab,我們新建更多tab,瀏覽更多頁面,並且跳轉到這些新tab下
這就像使用mui.openWindow()方法打開新的webview,該方法傳入一些參數,如下官方說法:
mui.openWindow({ url:new-page-url, id:new-page-id, styles:{ top:newpage-top-position,//新頁面頂部位置 bottom:newage-bottom-position,//新頁面底部位置 width:newpage-width,//新頁面寬度,默認為100% height:newpage-height,//新頁面高度,默認為100% ...... }, extras:{ .....//自定義擴展參數,可以用來處理頁面間傳值 }, createNew:false,//是否重復創建同樣id的webview,默認為false:不重復創建,直接顯示 show:{ autoShow:true,//頁面loaded事件發生后自動顯示,默認為true aniShow:animationType,//頁面顯示動畫,默認為”slide-in-right“; duration:animationTime//頁面動畫持續時間,Android平台默認100毫秒,iOS平台默認200毫秒; }, waiting:{ autoShow:true,//自動顯示等待框,默認為true title:'正在加載...',//等待對話框上顯示的提示內容 options:{ width:waiting-dialog-widht,//等待框背景區域寬度,默認根據內容自動計算合適寬度 height:waiting-dialog-height,//等待框背景區域高度,默認根據內容自動計算合適高度 ...... } } })
openWindow打開了一個新的webView並且跳轉到了新的webView,就像瀏覽器新建一個tab並且切換過去,只不過切換過程帶了參數,實現了動畫(這由native.js交給了原生動畫實現的),傳遞頁面參數,這也是比瀏覽器訪問網頁的強大之處
openWindow遇到已經打開過並且id仍然在緩存中的webview(這些webview通常是被hide()掉的),會直接跳轉過去,相當於getWebviewById().show()
openWindow有兩個核心參數,一個是url表示打開的html文件,打開tab也得知道網頁地址對吧?還一個是id,這個參數相當於句柄,以后尋找這個webview就靠它了,使用getWebviewById()方法抓到這個webview並進行操作!
請注意:openWindow下有一個特殊的參數:createNew
如果它為false,使用openWindow打開新窗口的時候,會先判斷是不是有一樣id的webview,如果有,直接跳過去,沒有的話,就新建一個窗口再跳過去!
如果它是true,使用openWindow打開新窗口的時候,不管有沒有相同id的tab,都回去新創建一個,也就是可能會創建重復ID的webview,這是很蛋疼的,因為會造成app跳轉webview時,與預期效果不同(跳轉的webview不是自己想要的),或者getWebviewById()返回的不是自己想要的webview對象,造成誤操作。
請盡量不要使用createNew,除非特殊的頁面需要創建重復的多個。
注:我遇到過創建了重復的webview后造成的自定義觸發事件(fire)發生了意想不到的結果,在返回前,對返回頁面的dom進行修改刷新,但dom並沒有被改變,其實是因為重復webview,修改了別的!
場景三:
我要關閉一個頁面!
方法一:隱藏掉(非真關閉),這樣會暫時從當前webview切出去,返回上一個webview,但是這樣不會清除這個webview,webview依然保存在緩存中。
此種方法用於不需要反復刷新創建的頁面,打開一次后長時間駐留在內存中的webview,使用plus.webview.getWebviewById().hide()隱藏,同理使用show()方法再次喚出這個webview
此種方法打開webview下的html是不會重新執行一遍JS,也不會再次渲染CSS了。一般采用自定義事件監聽,然后觸發相應的JS。
方法二:觸發mui.back()或返回事件,這里注意了back並不會像瀏覽器那樣history.go(-1)返回上一頁,而是相當於瀏覽器直接關閉當前tab!
就是說mui.back()將會關閉當前的webview后返回上一個webview,此時我們如果使用plus.webview.getWebviewById()獲取那個被返回的webview已經是查找不到,因為webview被關閉了,緩存也消失了。
下一次打開需要重新加載整個html頁面,重新執行一遍JS代碼,重新渲染一次CSS布局
方法三:不要返回,而要關閉指定的一個webview,那使用plus.webview.getWebviewById().close()即可,這是不帶返回效果的關閉某個頁面。
比如關閉當前的頁面,plus.webview.currentWebview().close(),這個方法的效果會和mui.back()一樣。
方法四:直接清理掉,清理掉的話將會導致頁面跳轉不產生動畫或者顯示加載中,因為頁面將被認為從未打開過,使用:plus.webview.getWebviewById().clear()
終極關閉大法:假設我設置的主頁是login.html,現在我的用戶退出了登陸,那么我要清空他已經打開的所有webview,不留使用痕跡,使用如下代碼:
toLogin = function() { var all = plus.webview.all(); var launch = plus.webview.getLaunchWebview() //基座,不可以關掉 for(var i = 0; i < all.length; i++) { if(all[i] === launch) continue; all[i].close(); all[i].clear(); } //立刻退出 setTimeout(function() { launch.show(); //不要重新打開login,app的基座就是login頁面,直接show出來就行了 }, 0); }
其中不能粗魯的把所有的webview統統關閉並清空,那將會導致app直接關閉,只要僅剩的最后一個webview被關閉,也就默認app退出,應保留基座:launchWebView(就是首頁)!
場景四:
打開已經打開過並且沒有被close或者clear的webview:
使用:plus.webview.getWebviewById().show()
使用:plus.webview.getWebviewById().hide() //隱藏掉
注意:被關閉(close)和清空(clear),返回掉(back)的webview將會返回null,不可以操作!並且每次重新openWindow打開的時候都會重新加載頁面,執行一遍頁面的JS代碼
總結一下webview!
mui提供的plus對象封裝了對webview的操作,hbuilder中輸入plus.webview即可獲取對象下面的變量
下面有三個get方法獲取webview:
分別獲取:基座(就是首頁),當前頂部頁面(其實就是當前顯示的),根據id獲得webview
返回的是WebViewObject,這個object下面有:
等等的方法,自行在hbuilder中查看吧!