当前位置: 代码网 > it编程>App开发>Android > WebView交互架构项目实战(一):使用与原理

WebView交互架构项目实战(一):使用与原理

2024年08月02日 Android 我要评论
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助。因此收集整理了一份《2024年Web前端开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点!

public void onloadresource(webview view, string url) {

super.onloadresource(view, url);

}

// 在加载 url 对应资源时会回调此方法,不同的是,可以通过返回值控制加载的数据。此方法已被废弃

// 若返回 null,webview 会正常加载该资源

// 若返回 webresourceresponse 类型的对象,则 webview 会使用该对象

// 需要注意的是,此方法不在 ui 线程中被调用

@override

public webresourceresponse shouldinterceptrequest(webview view, string url) {

return super.shouldinterceptrequest(view, url);

}

// 是上面方法的替代方法,使用方法和上面方法一致

@override

public webresourceresponse shouldinterceptrequest(webview view, webresourcerequest request) {

return super.shouldinterceptrequest(view, request);

}

// 加载资源出错时会被回调的方法

@override

public void onreceivederror(webview view, webresourcerequest request, webresourceerror error) {

super.onreceivederror(view, request, error);

}

// 加载资源时 http 请求出错会回调此方法

@override

public void onreceivedhttperror(webview view, webresourcerequest request, webresourceresponse errorresponse) {

super.onreceivedhttperror(view, request, errorresponse);

}

// 请求 https 资源出错时会回调此方法

@override

public void onreceivedsslerror(webview view, sslerrorhandler handler, sslerror error) {

super.onreceivedsslerror(view, handler, error);

}

// 拦截浏览器中的按键事件

// 若返回 true,则拦截按键事件

// 若返回 false,则由 webview 处理该事件

@override

public boolean shouldoverridekeyevent(webview view, keyevent event) {

return super.shouldoverridekeyevent(view, event);

}

// 当页面的缩放比例发生变化时会回调此方法

@override

public void onscalechanged(webview view, float oldscale, float newscale) {

super.onscalechanged(view, oldscale, newscale);

}

});

3. webchromeclient


同 webviewclient 一样,通过为 webview 设置 webchromeclient 对象,并重写其中的一些方法可以对 webview 的一些行为进行控制。

webview.setwebchromeclient(new webchromeclient() {

// 网页的加载进度

@override

public void onprogresschanged(webview view, int newprogress) {

l.i("onprogresschanged " + newprogress);

super.onprogresschanged(view, newprogress);

}

// 接收到网页的 title

@override

public void onreceivedtitle(webview view, string title) {

l.i("onreceivedtitle " + title);

super.onreceivedtitle(view, title);

}

// 接收到网页的 icon

@override

public void onreceivedicon(webview view, bitmap icon) {

super.onreceivedicon(view, icon);

}

@override

public void onreceivedtouchiconurl(webview view, string url, boolean precomposed) {

super.onreceivedtouchiconurl(view, url, precomposed);

}

// 当 h5 页面中点击播放的 flash video 的全屏按钮时,会调用这个方法

@override

public void onshowcustomview(view view, customviewcallback callback) {

super.onshowcustomview(view, callback);

}

// 与 onshowcustomview() 对应的取消全屏时会调用的方法

@override

public void onhidecustomview() {

super.onhidecustomview();

}

@override

public void onshowcustomview(view view, int requestedorientation, customviewcallback callback) {

super.onshowcustomview(view, requestedorientation, callback);

}

// http://www.cnblogs.com/ufreedom/p/4229590.html

// 当创建新的 window 时会调用此方法

@override

public boolean oncreatewindow(webview view, boolean isdialog, boolean isusergesture, message resultmsg) {

return super.oncreatewindow(view, isdialog, isusergesture, resultmsg);

}

// 和 oncreatewindow() 方法对应的,关闭 window

@override

public void onclosewindow(webview window) {

super.onclosewindow(window);

}

// 当 webview 获取焦点时会调用此方法

@override

public void onrequestfocus(webview view) {

super.onrequestfocus(view);

}

// 在 js 代码中弹出 alert 窗口时会调用此方法

@override

public boolean onjsalert(webview view, string url, string message, jsresult result) {

return super.onjsalert(view, url, message, result);

}

// 在 js 代码中弹出 confirm 窗口时会调用此方法

@override

public boolean onjsconfirm(webview view, string url, string message, jsresult result) {

return super.onjsconfirm(view, url, message, result);

}

// 在 js 代码中弹出 prompt 窗口时会调用此方法

@override

public boolean onjsprompt(webview view, string url, string message, string defaultvalue, jspromptresult result) {

return super.onjsprompt(view, url, message, defaultvalue, result);

}

// 在 js 加载之前会调用此方法

@override

public boolean onjsbeforeunload(webview view, string url, string message, jsresult result) {

return super.onjsbeforeunload(view, url, message, result);

}

// 打印 js 中的日志 console 信息,被废弃

@override

public void onconsolemessage(string message, int linenumber, string sourceid) {

super.onconsolemessage(message, linenumber, sourceid);

}

// 打印 js 中的日志 console 信息,被废弃

@override

public boolean onconsolemessage(consolemessage consolemessage) {

return super.onconsolemessage(consolemessage);

}

});

4. webviewclient 和 webchromeclient 的区别


webviewclient 主要帮助 webview 处理一些网络请求方面的行为和操作,比如:各种资源的请求、请求资源出现错误、https请求出现错误的通知等。

webchromeclient 主要帮助 webview 处理一些 javascript 相关的一些细节,比如:各种对话框的弹出、js 中日志信息的打印、window 的创建和关闭、以及 title 和 icon 的接收等。

5. js 和 java 代码的交互


java 代码和 js 代码额相互调用已经老生常谈了,现在也有一些很优秀的开源框架,使用起来非常的方便,但是其原理都是一样的,下面就介绍一下 js 代码和 java 代码是如何进行交互的。

5.1 js 代码调用 java 代码

private class innerclass {

private context mcontext = null;

public innerclass(context context) {

mcontext = context;

}

@javascriptinterface

public void toastmessage(string msg) {

toast.maketext(mcontext, msg, toast.length_short).show();

}

}

public class jsbridgeactivity extends appcompatactivity {

private webview webview = null;

@override

protected void oncreate(bundle savedinstancestate) {

super.oncreate(savedinstancestate);

setcontentview(r.layout.activity_jsbridge);

initwebview();

}

private void initwebview() {

webview = (webview) findviewbyid(r.id.webview);

webview.getsettings().setjavascriptenabled(true);

webview.addjavascriptinterface(new innerclass(jsbridgeactivity.this), “innerclass”);

webview.loadurl(“file:///android_asset/demo.html”);

webview.setwebchromeclient(new webchromeclient());

}

}

  • 有名为 innerclass 的类,其中的方法 toastmessage(string msg)@javascriptinterface 注解所修饰

  • 设置 webview 对象支持 javascript,并且调用 addjavascriptinterface(object object, string name) 方法,将 innerclass 的对象传入 webview 对象中

  • 在 webview 加载页面的 js 代码中,即可通过 name 调用 innerclass 对象的 toastmessage(string msg) 方法,如下所示:

function testprompt(){

window.innerclass.toastmessage(“jsbridge”);

}

5.2 java 代码调用 js 代码

假如有如下的 js 方法,如下所示:

function testconfirm(){

var temp = “temp”;

confirm(temp);

}

在 java 中可以通过如下方法调用该 js 方法:

webview.loadurl(“javascript:testconfirm()”);

注意

  • 在 java 代码中调用 js 代码弹出 alertconfirmprompt 对话框的时候,需要给 webview 设置 webchromeclient 对象才可以正常的弹出对话框,否则不会有效果。

  • java 调用 js 的代码需要在主线程中调用才会生效

  • 在 activity 的 oncreate() 方法中直接调用 webview.loadurl() 方法是不会生效的,需要在webview 加载完成之后再调用 js 的代码,才会生效。

6. webview 的缓存


6.1 cachemode 缓存模式

通过 webview 的 websettings 对象可以设置 webview 的 cachemode 缓存策略,共有如下几个值可供设置:

  • load_default:默认设置,如果有本地缓存,且缓存有效未过期,则直接使用本地缓存,否则加载网络数据

  • load_normal:已被废弃,同 load_default 效果一样

  • load_cache_else_network:如果存在缓存时,不论缓存是否过期,都使用缓存;若缓存不存在,则从网络获取数据

  • load_no_cache:不使用缓存,只从网络获取数据

  • load_cache_only:不从网络获取数据,只使用缓存数据

6.2 webview 缓存路径

我测试用的手机是小米 note,android 系统是 4.4,webview 缓存的文件存在于 /data/data/${package_name}/app_webview/cache/ 路径下

img

webviewcache.png

6.3 h5 缓存机制

h5 的缓存机制共有 5 种缓存机制,分别是:

  • 浏览器缓存机制:主要通过 http 的协议头中的 cache-control(或 expires)和 last-modified(或 etag)字段控制控制文件的缓存。

  • application cache(appcache)缓存机制:appcache 缓存是对浏览器缓存的补充,不可替代。

  • dom storage 缓存机制:dom storage 提供 5mb 大小的缓存空间,以键值对的形式存取文件。

  • web sql database 缓存机制:h5 提供了基于 sql 的数据库存储机制,用于存储一些结构化的数据。

  • indexed database 缓存机制:不同于 sql 数据库,属于 nosql 数据库。indexed database 存储的数据是以键值对的形式存储数据的。

共有这 5 种缓存机制,值得详细说明,在此就不再做过多的说明,争取后续单独写一篇博客介绍缓存机制。

7. webview 引起的内存泄露


activity 中使用 webview 有可能会出现内存泄露的情况,android 5.1 webview内存泄漏分析【android】 webview内存泄漏优化之路 这两篇文章已经介绍的很详细。

android 5.1 中,如果 webviewdestroy() 方法在 ondetachedfromwindow() 方法之前被执行,则会出现 webview 持有 activity 的引用,从而导致内存泄露。

为了避免 webview 引起内存泄露,有两个比较有效的办法:

  • 使用代码 new 一个 webview 对象,而不是在 xml 文件中静态写入一个 webview

  • activityondestory() 方法中,主动的将 webview 从父容器中移除并销毁该 webview 对象,如下所示:

@override

protected void ondestroy() {

super.ondestroy();

if (webview != null) {

viewparent viewparent = webview.getparent();

if (viewparent != null) {

((viewgroup) viewparent).removeview(webview);

}

webview.getsettings().setjavascriptenabled(false);

webview.clearhistory();

webview.clearview();

webview.removeallviews();

webview.destroy();

}

}

最后

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、oppo等大厂,18年进入阿里一直到现在。

深知大多数初中级android工程师,想要提升技能,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助。

因此收集整理了一份《2024年web前端开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上android开发知识点!不论你是刚入门android开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

}

最后

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、oppo等大厂,18年进入阿里一直到现在。

深知大多数初中级android工程师,想要提升技能,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助。

因此收集整理了一份《2024年web前端开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

[外链图片转存中…(img-fetgmr5q-1715025449103)]

[外链图片转存中…(img-jimewtaa-1715025449103)]

[外链图片转存中…(img-ge0jurtc-1715025449103)]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上android开发知识点!不论你是刚入门android开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com