其实webview加载资源的速度并不慢,但是如果资源多了,当然就很慢。图片、css 、js 、html这些资源每个大概需要10-200ms ,一般都是30ms就ok了。不过webview是必须等到全部资源都完成加载,才会进行渲染的,所以加载的速度很重要!从google上我们了解到,webview加载页面的顺序是:先加载html,然后从里面解析出css、js文件和页面上的图片资源进行加载。如果webkit的缓存里面有,就不加载。加载完这些资源之后,就进行css的渲染和js的执行。css的渲染一般不需要很长时间,几十毫秒就ok。关键是js的执行,如果用了jquery,则执行起来需要5-6秒。而在这段时间,如果不在webview里设置背景,网页部分是白色的,很难看。这是一个很糟糕的用户体验。所以#欧#柏泰#克建议如果用网页布局程序,最好别用那些庞大的js框架。最好使用原生的js写业务脚本,以提升加载速度,改善用户体验。
在混合开发中,有时会用到安卓原生sdk,如调用相机、查看相册、录音等,这就需要web页面中的javascript能调用到安卓sdk接口。由于android的webview是基于webkit内核的,集成了js与java互调的接口函数,可以方便地进行开发使用。
界面布局xml:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
<relativelayout xmlns:android= "http://schemas.android.com/apk/res/android" xmlns:tools= "http://schemas.android.com/tools" android:layout_width= "match_parent" android:layout_height= "match_parent" > <webview android:id= "@+id/webview" android:layout_width= "fill_parent" android:layout_height= "fill_parent" android:layout_above= "@+id/linearlayout" /> <linearlayout android:id= "@+id/linearlayout" android:layout_width= "match_parent" android:layout_height= "wrap_content" android:layout_alignparentbottom= "true" > <button android:id= "@+id/btn" android:layout_width= "wrap_content" android:layout_height= "wrap_content" android:text= "java调用javascript接口" > </button> </linearlayout> </relativelayout> |
java代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
|
private webview webview; private handler handler = new handler(); private button button; @suppresslint ( "setjavascriptenabled" ) @override protected void oncreate(bundle savedinstancestate) { super .oncreate(savedinstancestate); setcontentview(r.layout.activity_main); webview = (webview) findviewbyid(r.id.webview); //自定义webview设置 websettings websettings = webview.getsettings(); websettings.setjavascriptenabled( true ); webview.addjavascriptinterface( new myjavascriptinterface(mainactivity. this ), "javainterface" ); //如果注释了,javascript中的alert弹窗等就会失效,不显示 webview.setwebchromeclient( new webchromeclient()); //webview.setwebchromeclient(new mywebchromeclient()); //测试webview加载是否正常 //webview.loadurl("http://www.baidu.com/"); webview.setwebviewclient( new hellowebview()); webview.loadurl( "file:///android_asset/index.html" ); button = (button) findviewbyid(r.id.btn); button.setonclicklistener( new view.onclicklistener() { @override public void onclick(view v) { string param = "bb" ; webview.loadurl( "javascript:showtitle('" +param+ "')" ); } }); } private class hellowebview extends webviewclient{ @override public boolean shouldoverrideurlloading(webview view, string url) { // todo auto-generated method stub view.loadurl(url); return true ; } } /** * 在主线程中定义javascript可以调用的安卓接口 * @author chq * api 以后,每个被调用java函数都要叫声明 @javascriptinterface */ public class myjavascriptinterface{ private context context; public myjavascriptinterface(context context){ this .context = context; } @javascriptinterface public string tostring() { return "this is interface" ; } @javascriptinterface public void clickonandroid() { toast.maketext(context, "js调用安卓:...." , toast.length_short).show(); } /** * 安卓调用js接口,要开启子线程调用 */ @javascriptinterface public void call() { toast.maketext(context, "安卓客户端再调用javascript接口" , toast.length_short).show(); handler.post( new runnable() { @override public void run() { string param = "bb" ; webview.loadurl( "javascript:showtitle('" +param+ "')" ); } }); } } |
其中:有几点必须注意的,网上早期关于webview的描述中,有几点变化。1)安卓4.2以上的版本中使用webview实现java与js互调,java接口需要声明@javascriptinterface ; 2)webview要调用setwebchromeclient(),以适应js等弹窗等实现;3)addjavascriptinterface中绑定的接口中调用javascript接口,需要开启子线程来调用(报错:caused by: java.lang.throwable: a webview method was called on thread 'javabridge'. all webview methods must be called on the same thread. );
html代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
<html> <script type= "text/javascript" > //安卓定义的接口1 function callandroidinterface() { window.javainterface.clickonandroid(); } // function showtitle(param) { alert( "传参:" +param); var x = document.getelementbyid( "title" ); alert( "标题:" +x.innerhtml); } </script> <body> <h3 id= "title" >关于安卓与javascript的交互</h3> <input type= "button" value= "调用接口1" onclick= "callandroidinterface()" ></input> <input type= "button" value= "测试接口可用性" onclick= "showtitle('aa')" ></input> <input type= "button" value= "调用接口2" onclick= "window.javainterface.call()" ></input> </body> </html> |
以上html文件,其中javainterface就是webview中addjavacriptinterface()方法中注入的接口入口名称,通过该名称就可以直接调用java中的接口。(该html页面需要保持到项目assets目录中,由webview.loadurl("file:///android_asset/index.html")来加载);
效果图:
其中,对话框弹出:网址为"file://"的网页显示:,如果是服务器上的web页面就会显示源ip地址等等,显然不是我们想要的。下一篇,我们可以重写webchromeclient来修改对话框、确认框等webview的优化。
以上内容是针对android webview上实现javascript与java交互的全部内容,希望对大家有所帮助!