標籤:style blog http java color 使用
5月份開發了臉萌WP版,其中需要使用web技術來繪製映像,於是就使用了原生webbrowser控制項。在使用webbrowser control的過程中,發現了一些坑,也總結的幾個小技巧,分享給大家。
首先我們需要瞭解下webbrowser control,與案頭windows平台上的webbrowser一樣,都是基於IE核心封裝的web展示控制項,用法與wpf基本一致,同時也是非託管資源,但wp平台上沒有實現IDispose介面,帶了了記憶體控制的挑戰。此外,webbrowser本身支援有限的js script和c#代碼互動,帶來了更多的可操作性。
1.c#調用webbrowser function
這裡主要是指使用本地代碼(C#)和webbrowser載入的Javascript代碼的互動行為,利用此方法可以很容易的實現web項目對wp原生項目的移植,這對web開發人員來講是很方便的。這裡主要給大家介紹2個API:分別是InvokeScript()方法以及ScriptNotify事件。
InvokeScript方法可以傳參並執行webbrowser載入的javascript代碼中的函數,實現對應的效果,用法如下:
webbrowser.InvokeScript("initPerson");webbrowser.InvokeScript("initPerson", new string[] {"0","2001","1" });
第一段就是簡單的調用js function,第二行則是傳遞參數並調用js function。這兩種方法使用起來很靈活,足以來處理很多的互動行為。以臉萌WP版為例,我在C#中處理各種使用者行為,並將獲得的參數傳入webbrowser,js 指令碼響應後會動態執行,使用web技術繪製出我想要的頭像,這非常靈活。
同時,對js 函數適當的封裝可以提高互動效率,因為InvokeScript可傳入的參數類型只能為 string[],js函數不恰當的封裝會導致互動的困難,甚至是無法互動,下面我舉例說明:
var personA = { ‘eye‘: { ‘id‘: 0 }, ‘hair‘: { ‘id‘: 0 } }; function initPerson(person) { a = person.eye.id; b = person.hair.id; }
這裡的initPerson函數需要直接傳入javascript對象,這是InvokeScript難以直接傳入的,但我們可以進行簡單的封裝,就可以順利的實現意圖,如下:
var personA = { ‘eye‘: { ‘id‘: 0 }, ‘hair‘: { ‘id‘: 0 } }; function initPerson(person) { a = person.eye.id; b = person.hair.id; } function drawPerson(eyeId, hairId) { personA.eye.id = eyeId; personA.hair.id = hairId; initPerson(personA); }
這樣C#就直接可以寫為:
webbrowser.InvokeScript("drawPerson", new string[] {"0","2001" });
能夠順利的實現互動,以上只是方法之一,大家還可以直接傳入一個字串,然後再在javascript中進行處理,如下:
function initPerson(person) { if (typeof person == ‘string‘) var person = eval(person); a = person.eye.id; b = person.hair.id; }
C#:
webbrowser.InvokeScript("initPerson", "{ ‘eye‘: {‘id‘: 0 }, ‘hair‘: { ‘id‘: 0}}");
藉助神奇的eval()函數,同樣可以實現我們想要的效果。MVP郝冠軍告訴我,使用eval並不恰當,可以使用Native json API來替代,大家可以自行搜尋下用法,使用方式和eval一致。
2.webbrowser調用C#指令碼
這裡使用的API主要是ScriptNotify事件,可以實現javascript函數調用c#指令碼的效果,能夠動態改變整個應用的行為,這能夠使得基於web技術的app調用更進階的原生功能,包括位置,推送,動態磚等等,是不是覺得很棒呀,下面我們來看簡單的實現方式。
首先webbrowser需要註冊ScriptNotify事件,以接收來自javascript的資訊
webbrowser.ScriptNotify += (e, g) => { //響應代碼 var result = g.Value; };
同時,javascript發送資料方式如下:
window.external.notify("參數");
如此即可實現webbrowser與整個app的動態互動,這是非常便利的。
3.webbrowser的記憶體控制
由於webbrowser是非託管資源,同時wp上未實現IDispose介面,這給app的記憶體帶來了很大壓力,每次導航都可以明顯發現有20M左右記憶體沒有釋放,經過多次檢查,發現是webbrowser的資源沒有釋放,同時也發現強制GC也沒有任何效果,最終經過一番學習,通過js來進行釋放,大幅減小了記憶體的消耗,但仍不徹底,諸位大牛如果有好的辦法可以指點下我。下面是我的方法:
js中將所有使用的資源都做空處理:
function memoryRelease() { personA = null; window = null; }
C#每次在離開當前頁面時執行它:
protected override void OnNavigatedFrom(NavigationEventArgs e) { webbrowser.InvokeScript("memoryRelease"); }
通過這種方式可以有效減少記憶體流失,僅做拋磚引玉只用。
最後,silverlight架構下的webbrowser控制項雖然坑不少,但仍是一個非常靈活的控制項,這對於使用html5開發跨平台app的開發人員來講,是個非常棒的方式。