Webview开发及性能优化

Webview现状

 

版本

内核

描述

<19(Android 4.4)

Android Webkit内核

对HTML5的支持不是很好,js存在安全漏洞

>=19

 

Chromium内核

 

Android5.0开始

 

WebView移植成了一个独立的apk

Android7.0

 

安装Chrome (version>51),那么Chrome将会直接为应用的WebView提供渲染,WebView版本会随着Chrome的更新而更新,用户也可以选择WebView的服务提供方(在开发者选项->WebView Implementation里),WebView可以脱离应用,在一个独立的沙盒进程中渲染页面

 

Android8.0

 

默认开启WebView多进程模式,即WebView运行在独立的沙盒进程中

Webview 配置

public static void setDefaultWebSettings(WebView webView) {
    WebSettings webSettings = webView.getSettings();
    //允许js代码
    webSettings.setJavaScriptEnabled(true);
    //禁用放缩
    webSettings.setDisplayZoomControls(false);
    webSettings.setBuiltInZoomControls(false);
    //禁用文字缩放
    webSettings.setTextZoom(100);
    //设置浏览器缓存
    webSettings.setCacheMode(WebSettings.LOAD_NO_CACHE);
    //缓存模式如下:
    //LOAD_CACHE_ONLY: 不使用网络,只读取本地缓存数据
    //LOAD_DEFAULT: (默认)根据cache-control决定是否从网络上取数据。
    //LOAD_NO_CACHE: 不使用缓存,只从网络获取数据.
    //LOAD_CACHE_ELSE_NETWORK,只要本地有,无论是否过期,或者no-cache,都使用缓存中的数据。
    //5.0以上开启混合模式加载
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
        webSettings.setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);
    }
//是否使用预览模式加载界面
    webSettings.setLoadWithOverviewMode(true);
//设置WebView是否使用viewport
    webSettings.setUseWideViewPort(true);
    //允许SessionStorage/LocalStorage存储
    webSettings.setDomStorageEnabled(true);
    //10M缓存,api 18后,系统自动管理。
    webSettings.setAppCacheMaxSize(10 * 1024 * 1024);
    //允许App缓存
webSettings.setAppCacheEnabled(true);
//设置App缓存地址
    webSettings.setAppCachePath(context.getDir("appcache", 0).getPath());
    //允许WebView使用File协议
    webSettings.setAllowFileAccess(true);
    //不保存密码
    webSettings.setSavePassword(false);
    //设置UA
    webSettings.setUserAgentString(webSettings.getUserAgentString() + "kaolaApp/" + AppUtils.getVersionName());
    //移除部分系统JavaScript接口
    KaolaWebViewSecurity.removeJavascriptInterfaces(webView);
    //自动加载图片
    webSettings.setLoadsImagesAutomatically(true);
}

WebViewClient类

处理各种通知、请求事件

常用方法:

  1. shouldOverrideUrlLoading():加载超链接时回调过来,通过重写可以实现对网页中超链接的拦截
  2. onPageStarted():开始载入页面调用的,我们可以设定一个loading的页面,告诉用户程序在等待网络响应。
  3. onPageFinished():在页面加载结束时调用。我们可以关闭loading 条,切换程序动作。或者执行js注入
  4. shouldInterceptRequest():在加载页面资源时会调用,每一个资源(比如图片)的加载都会调用一次,可以进行本地资源监测、替换或缓存
  5. onReceivedError():加载页面的服务器出现错误时(如404)调用。
  6. onReceivedSslError():处理https请求c出错

WebChromeClient类

辅助 WebView 处理 Javascript 的对话框,网站图标,网站标题等等。

常用方法:

  1. onProgressChanged():获得网页的加载进度并显示
  2. onReceivedTitle():获取Web页中的标题
  3. onJsAlert ():拦截Alert
  4. onJsPrompt():拦截Prompt
  5. onJsConfirm():拦截Confirm

缓存

Android WebView自带的缓存机制有5种:

  1. 浏览器缓存机制
  2. App Cache
  3. Dom Storage
  4. Web SQL Database缓存机制
  5. Indexed Database 缓存机制
  6. File System缓存机制

https://blog.csdn.net/carson_ho/article/details/71402764

 

JS-Native交互

WebSettings.setJavaScriptEnabled(true);在Android 4.4(<19)以下版本存在安全漏洞,

如果启用了JavaScript,务必做好安全措施,防止远程执行漏洞

@TargetApi(11)
private static final void removeJavascriptInterfaces(WebView webView) {
    try {
        if (Build.VERSION.SDK_INT >= 11 && Build.VERSION.SDK_INT < 17) {
            webView.removeJavascriptInterface("searchBoxJavaBridge_");
            webView.removeJavascriptInterface("accessibility");
            webView.removeJavascriptInterface("accessibilityTraversal");
        }
    } catch (Throwable tr) {
        tr.printStackTrace();
    }
}

在Android 4.4上通过注解@JavascriptInterface方式建立Javascript对象和android原生对象的绑定

java调用JavaScript

  1. webview.loadUrl(“javascript:”)
  2. webview.evaluateJavascript() Android4.4版本开始支持,方法最大的好处就是能够直接在一次执行的时候获取到 JS 返回的结果
    webView.evaluateJavascript("javascript:Date.now()", new ValueCallback<String>() {
        @Override
        public void onReceiveValue(String value) {
            System.out.println(value); 
        }
    });

JavaScript调用Java

  1. 通过addJavascriptInterface()进行对象映射
    webView.addJavascriptInterface(new JSInterface(),"android");
    class JSInterface{
        @JavascriptInterface
        public void getUserInfo(){}
        @JavascriptInterface
        public void getDeviceInfo(){}
    }

     

  2. WebViewClient 的shouldOverrideUrlLoading ()方法回调拦截 url
    webView.setWebViewClient(new WebViewClient() {
        @Override
        public boolean shouldOverrideUrlLoading(WebView view, String url) {
            if(url.equals('sdk:hello')) {
                System.out.println('hello world');
                return true;
            }
            return super.shouldOverrideUrlLoading(view, url);
        }
    });

     

  3. 方法劫持方法劫持主要是利用 JS 的一些方法执行时会触发 Android 客户端中的一些回调如:WebChromeClient的onJsAlert、onJsPrompt、onJsConfirm、onConsoleMessage方法
    private class hijackWebChromeClient extends WebChromeClient {
        @Override
        public boolean onJsPrompt(WebView view,String url, String message, String defaultValue, JsPromptResult result) {
            if (this.hijack(message)) {
                return true;
            }
            return super.onJsPrompt(view, url, message, defaultValue, result);
        }
    }
    //注入劫持回调类
    WebView webview = (WebView) findViewById(R.id.webview);
    webview.loadUrl('http://imnerd.org');
    webview.setWebChromeClient(new hijackChromeClient);

     

以上讲述了 JS 调用客户端的方法,以及客户端调用前端的方法。除了这两种单向调用的方式之外,往往比较多的是 JS 调用客户端方法,客户端再调用 JS 返回结果的双向调用。在 JS 调用的时候需要传入一个回调方法名,然后客户端直接执行回调方法。

JsBridge

该项目在Java和JavaScript之间架起了一座桥梁。它提供了从js调用Java代码并从java调用js代码的安全方便的方法。

传送门:https://github.com/lzyzsd/JsBridge

当然也有很多其他的方案,但思想大都一致。

调试:

优化:

Web具有快速迭代发布的天然优势,但也存在中一些让人诟病的问题,比如加载速度慢,体验差等。但现在有很多优化框架来解决这些问题,优化后虽说不能媲美Native,但也不是那么差,当然这个过程需要前后端的配合。

VasSonic:轻量级高性能Hybrid框架

CandyWebCache是移动端web资源的本地缓存解决方案

首屏优化:

如何缩短这些过程的时间,就成了优化WebView性能的关键。优化主要从webview的初始化、加载、渲染这几个方向进行

WebView初始化

初始化webview设计到浏览器内核初始化,还只能在主线程中执行。

首次初始化时间

二次初始化时间

403ms

22.5m‬s

解决方案:提前初始化,并创建一个WebView缓存池(需要多个webview做转场动画)

public class GMWebViewPool {
    /**
     * 创建WebView实例
     * 用了applicationContext
     */
    public void prepareNewWebView(Context context) {
        if (mCachedWebViewStack.size() < CACHED_WEBVIEW_MAX_NUM) {
            mCachedWebViewStack.push(new GMWebView(new MutableContextWrapper(context.getApplicationContext())));
        }
    }
    /**
     * 从缓存池中获取合适的WebView
     *
     * @param context activity context
     * @return WebView
     */
    public GMWebView acquireWebViewInternal(Context context) {
        // 为空,直接返回新实例
        if (mCachedWebViewStack == null || mCachedWebViewStack.isEmpty()) {
            return new GMWebView(context);
        }
        GMWebView webView = mCachedWebViewStack.pop();
        // webView不为空,则开始使用预创建的WebView,并且替换Context
        MutableContextWrapper contextWrapper = (MutableContextWrapper) webView.getContext();
        contextWrapper.setBaseContext(context);
        return webView;
    }
}

MutableContextWrapper,作为Context的一个中间层。我们会将Activity context包在MutableContextWrapper里面,destory的时候,会将WebView的Context设置为Application的Context,从而释放Activity Context。

//precreate WebView
MutableContextWrapper contextWrapper = new MutableContextWrapper(BaseApplicationImpl.sApplication);
mPool[0] = new WebView(contextWrapper);

//reset WebView 
ct =(MutableContextWrapper)webview.getContext();
ct.setBaseContext(getApplication());

//reuse WebView
((MutableContextWrapper)webview.getContext()).setBaseContext(activityContext);

优化后:

WebView初始化

3ms

待续

  1. 腾讯x5浏览器
  2. 框架使用VasSonic、CandyWebCache
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
腾讯X5内核是一款支持多进程、支持硬件加速、支持自定义内核扩展的WebView内核。在Android开发中,使用腾讯X5内核可以提高WebView的性能和稳定性,下面是一些优化和实践总结: 1. 引入腾讯X5内核 引入腾讯X5内核需要在项目中添加相应的依赖库,然后在代码中进行初始化和使用。具体步骤可以参考腾讯官方文档。 2. 启用硬件加速 在使用腾讯X5内核时,可以启用硬件加速来提高WebView的渲染速度。具体可以通过设置WebView的LayerType属性来实现,例如: ``` webView.setLayerType(View.LAYER_TYPE_HARDWARE, null); ``` 3. 使用预加载 预加载可以在用户点击链接之前就开始加载下一页的内容,以提高用户体验和减少页面加载时间。腾讯X5内核提供了预加载功能,可以通过设置WebView的预加载模式来实现,例如: ``` webView.getX5WebViewExtension().setPageCacheCapacity(5); // 设置最大缓存页面数为5 webView.getX5WebViewExtension().setPreload(true); // 开启预加载模式 ``` 4. 优化JSBridge通信 JSBridge是一种用于WebView和Native代码之间通信的技术,但是在使用过程中容易出现性能问题。为了优化JSBridge通信,可以使用腾讯X5内核提供的基于V8引擎的JSBridge,它可以提高通信效率和稳定性。 5. 避免WebView内存泄漏 在使用WebView时,需要注意避免内存泄漏问题。具体可以通过以下方式来避免: - 及时释放WebView对象 - 使用静态内部类或弱引用来持有WebView对象 - 在Activity的onDestroy()方法中调用WebView的destroy()方法 总之,腾讯X5内核是一款非常强大的WebView内核,可以帮助我们优化WebView的性能和稳定性。在使用中,需要注意以上几点优化和实践。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值