5月份开发了脸萌WP版,其中须要使用web技术来绘制图像,因而就使用了原生webbrowser控件。在使用webbrowser control的过程当中,发现了一些坑,也总结的几个小技巧,分享给你们。javascript
首先咱们须要了解下webbrowser control,与桌面windows平台上的webbrowser同样,都是基于IE内核封装的web展现控件,用法与wpf基本一致,同时也是非托管资源,但wp平台上没有实现IDispose接口,带了了内存控制的挑战。此外,webbrowser自己支持有限的js script和c#代码交互,带来了更多的可操做性。html
1.c#调用webbrowser functionhtml5
这里主要是指使用本地代码(C#)和webbrowser加载的Javascript代码的交互行为,利用此方法能够很容易的实现web项目对wp原生项目的移植,这对web开发者来说是很方便的。这里主要给你们介绍2个API:分别是InvokeScript()方法以及ScriptNotify事件。java
InvokeScript方法能够传参并执行webbrowser加载的javascript代码中的函数,实现对应的效果,用法以下:web
webbrowser.InvokeScript("initPerson"); webbrowser.InvokeScript("initPerson", new string[] {"0","2001","1" });
第一段就是简单的调用js function,第二行则是传递参数并调用js function。这两种方法使用起来很灵活,足以来处理不少的交互行为。以脸萌WP版为例,我在C#中处理各类用户行为,并将得到的参数传入webbrowser,js 脚本响应后会动态执行,使用web技术绘制出我想要的头像,这很是灵活。json
同时,对js 函数适当的封装能够提升交互效率,由于InvokeScript可传入的参数类型只能为 string[],js函数不恰当的封装会致使交互的困难,甚至是没法交互,下面我举例说明:c#
var personA = { 'eye': { 'id': 0 }, 'hair': { 'id': 0 } }; function initPerson(person) { a = person.eye.id; b = person.hair.id; }
这里的initPerson函数须要直接传入javascript对象,这是InvokeScript难以直接传入的,但咱们能够进行简单的封装,就能够顺利的实现意图,以下:windows
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中进行处理,以下:app
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; CollectGarbage(); }
C#每次在离开当前页面时执行它:
protected override void OnNavigatedFrom(NavigationEventArgs e) { webbrowser.InvokeScript("memoryRelease"); }
CollectGarbage()是IE的一个特有属性,用于释放内存的,使用方法应该是,将该变量或引用对象,设置为null或delete,而后在进行释放动做。
经过这种方式能够有效的减小内存泄漏,仅作抛砖引玉只用。
最后,silverlight架构下的webbrowser控件虽然坑很多,但还是一个很是灵活的控件,这对于使用html5开发跨平台app的开发者来说,是个很是棒的方式。