WebView交互架构项目实战(一),成功入职腾讯月薪45K

WebView交互架构项目实战(一),成功入职腾讯月薪45K,第1张

WebView交互架构项目实战(一),成功入职腾讯月薪45K

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 代码中d出 alert 窗口时会调用此方法

@Override

public boolean onJsalert(WebView view, String url, String message, JsResult result) {

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

}

// 在 Js 代码中d出 Confirm 窗口时会调用此方法

@Override

public boolean onJs/confirm/i(WebView view, String url, String message, JsResult result) {

return super.onJs/confirm/i(view, url, message, result);

}

// 在 Js 代码中d出 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 相关的一些细节,比如:各种对话框的d出、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 代码d出 alert、/confirm/i 和 prompt 对话框的时候,需要给 WebView 设置 WebChromeClient 对象才可以正常的d出对话框,否则不会有效果。

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/ 路径下

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 中,如果 WebView 的 destroy() 方法在 onDetachedFromWindow() 方法之前被执行,则会出现 WebView 持有 Activity 的引用,从而导致内存泄露。

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

使用代码 New 一个 WebView 对象,而不是在 xml 文件中静态写入一个 WebView。

在 Activity 的 onDestory() 方法中,主动的将 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();

}

}


本文中涉及到的自定义类的源码都在 Github 上的 WebViewPractice 工程中。


参考资料:

Android 5.1 WebView内存泄漏分析 – 永远即等待

Android:手把手教你构建 WebView 的缓存机制 & 资源预加载方案 – Carson_Ho

【Android】 WebView内存泄漏优化之路 – kaka’s blog

Android WebView 性能轻量优化

WebView缓存原理分析和应用 – UncleChen的博客

文末


欢迎关注我的CSDN,分享Android干货,交流Android技术。

对文章有何见解,或者有何技术问题,都可以在评论区一起留言讨论,我会虔诚为你解答。

最后,如果你想知道更多Android的知识或需要其他资料我这里均免费分享,只需你多多支持我即可哦!

——可以直接点这里可以看到全部资料内容免费打包领取。
) 工程中。


参考资料:

Android 5.1 WebView内存泄漏分析 – 永远即等待

Android:手把手教你构建 WebView 的缓存机制 & 资源预加载方案 – Carson_Ho

【Android】 WebView内存泄漏优化之路 – kaka’s blog

Android WebView 性能轻量优化

WebView缓存原理分析和应用 – UncleChen的博客

文末


欢迎关注我的CSDN,分享Android干货,交流Android技术。

对文章有何见解,或者有何技术问题,都可以在评论区一起留言讨论,我会虔诚为你解答。

最后,如果你想知道更多Android的知识或需要其他资料我这里均免费分享,只需你多多支持我即可哦!

——可以直接点这里可以看到全部资料内容免费打包领取。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5708546.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-17
下一篇 2022-12-17

发表评论

登录后才能评论

评论列表(0条)

保存