Android Webview解析

一.Webview简单使用

二.Webview中Android方法和 js方法互调

三.Webview缓存机制

四.Webview优化

 

一.Webview简单使用

打开一个url

lateinit var web:WebView

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        val url = "https://www.baidu.com/"
        web = findViewById(R.id.web_url)
        val setting = web.settings
        setting.javaScriptEnabled = true
        web.webViewClient = object :WebViewClient(){
            override fun shouldOverrideUrlLoading(view: WebView?, request: WebResourceRequest?): Boolean {
                web.loadUrl(url)
                return false
            }
        }
        web.loadUrl(url)
    }

重写WebViewClient接口的目的是为了不让跳到手机自带浏览器打开这个URL,而是在webview中显示。

Webview常用的方法:

1.loadUrl 加载url

2.loadData 加载html数据

3.loadDataWithBase 加载html数据

4.setWebViewClient 如果用户设置了webviewclient,则在点击新的链接以后就不会跳转到系统浏览器了,而是在webview中显示。
setWebViewClient 中的方法:
shouldOverrideUrlLoading() 返回true表示你已经处理此次请求。返回false表示有webview自行处理。
shouldInterceptRequest()   可在这个方法中进行网页资源替换。
onPageStarted()            表示页面开始加载    
onPageFinished()           表示页面加载完成 
onReceiveError()           表示页面加载错误
onReceivedSslError()       为webview处理ssl设置

5. setWebChromeClient
onProgressChanged()        加载进度

WebSetting配置:

1. 支持js
settings.setJavaScriptEnabled(true);
2. 设置缓存方式,主要有以下几种:
LOAD_CACHE_ONLY: 不使用网络,只读取本地缓存数据。
LOAD_DEFAULT: 根据cache-control决定是否从网络上取数据。
LOAD_CACHE_NORMAL: API level 17中已经废弃, 从API level 11开始作用同LOAD_DEFAULT模式。
LOAD_NO_CACHE: 不使用缓存,只从网络获取数据。
LOAD_CACHE_ELSE_NETWORK:只要本地有,无论是否过期,或者no-cache,都使用缓存中的数据。
settings.setCacheMode(WebSettings.LOAD_NO_CACHE);
3. 开启DOM storage API功能(HTML5 提供的一种标准的接口,主要将键值对存储在本地,在页面加载完毕后可以通过 JavaScript 来操作这些数据。)
settings.setDomStorageEnabled(true);
4. 设置数据库缓存路径
settings.setDatabasePath(cacheDirPath);
5. 设置Application Caches缓存目录
settings.setAppCachePath(cacheDirPath);
6. 设置默认编码
settings.setDefaultTextEncodingName(“utf-8”);
7. 将图片调整到适合webview的大小
settings.setUseWideViewPort(false);
8. 支持缩放
settings.setSupportZoom(true);
9. 支持内容重新布局
settings.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.SINGLE_COLUMN);
10. 多窗口
settings.supportMultipleWindows();
11. 设置可以访问文件
settings.setAllowFileAccess(true);
12. 当webview调用requestFocus时为webview设置节点
settings.setNeedInitialFocus(true);
13. 设置支持缩放
settings.setBuiltInZoomControls(true);
14. 支持通过JS打开新窗口
settings.setJavaScriptCanOpenWindowsAutomatically(true);
15. 缩放至屏幕的大小
settings.setLoadWithOverviewMode(true);
16. 支持自动加载图片
settings.setLoadsImagesAutomatically(true);

 

二.Webview中Android方法和js方法互调

 H5代码:



   
      
	 java调用Js方法
   
     
	 
          
webView显示

在方法中创建了一个js方法和一个Button按键

Android调用js方法:

 web.loadUrl("javascript:showToast()") //android调用js方法

 

H5调用Android方法:

创建一个类,并创建一个方法,这个方法就是被H5调用的方法。注意:必须要添加@JavascriptInterface注解

class JSInterface {
        @JavascriptInterface
        fun showInfo(arg:String) {
            Log.e("tag", arg)
        }
    }
 web.addJavascriptInterface(JSInterface(),"Android")//js调用android方法

addJavascriptInterface方法的第一个参数是上面创建类的对象。window.Android.showInfo('从js中传输的参数值')中的Android就是第二参数传入的值。

 

三.Webview缓存机制

Android webview提供的缓存机制有5种:

1.浏览器缓存机制

2.Application Cache缓存机制

3.Dom Storage缓存机制

4.Web SQL DataBase缓存机制

5.Indexed Database缓存机制

 

1.浏览器缓存机制

原理:根据Http协议头里的Cache-Control(或Expires) 和 Last-Modified(或Etag)等字段来控制文件缓存机制

1.1 Expires 这个字段是存在于服务器响应头中,目的是告诉浏览器这个资源的过期时间。当还未过期时使用的是缓存,过期后再向服务器请求数据。Expires是是Http1.0标准中的字段。

1.2 Cache-Control 和 Expires 的机制类似。Cache-Control是Http1.1标准中新加的字段。当两个同时出现时,Cache-Control优先级最高。

1.3 Etag 这个字段是存在于服务器响应头中,它代表了该资源在服务器的唯一性。Etag的默认值是由索引(INODE),文件大小(SIZE)和最后改变文件的时间(TIME)进行Hash后得到的。Etag值的生成规则可以通过服务器生成。

实现机制:

在向服务器查询文件是否有更新时,浏览器通过 if-None-Match字段把特征字串发送给服务器,由服务器和文件最新特征字串进行匹配,来判断文件是否有更新,没有更新回包304;有更新回包200;

1.4 Last-Modified 标识文件在服务器上的最新更新时间

实现机制:

当下次请求时,如果文件缓存过期,浏览器通过if-Modified-Since字段带上这个时间,发送给服务器,由服务器比较时间戳来判断文件是否有修改。如果没有修改,服务器返回304告诉浏览器继续使用缓存;如果有修改,则返回200,同时返回最高的文件。

 

常见用法是:

Cache-Control 与 Last-Modified 一起使用,Expires 与 Etag 一起使用。

即一个用于控制缓存有效时间,一个用于在缓存失效后,向服务查询是否有更新。

 

2.Application Cache缓存机制




在标签html中使用 manifest属性,并引用appcache文件。

一个完整的appcache文件包含3个section

CACHE MANIFEST
 
# 2018-06-12
 
/demo.js
 
NETWORK:
 
*
 
FALLBACK:
 
/fail.html

CACHE MANIFEST 表示要缓存的文件

NETWORK 表示要加载的文件

FALLBACK 表示在页面加载失败后显示的页面

实现机制:

AppCache在首次加载生成后,也有更新机制。被缓存的文件如果需要更新,需要更新manifest文件因为浏览器在下次加载时,除了会默认使用缓存外,还会在后台检查manifest文件有没有修改,发现有修改,就会重新获取manifest文件,对Section:CACHE MANIFEST 下文件列表检查更新。

代码实现:
val cacheDirPath = this.filesDir.absolutePath+"cache/"
setting.setAppCachePath(cacheDirPath)//设置缓存路径
setting.setAppCacheEnabled(true)//开启Application cache存储机制

3.Dom Storage缓存机制

这种缓存机制分为两种:sessionStorage localStorage

sessionStorage 是临时性的,存储页面相关的数据,页面关闭后不能使用。

localStorage 是持久性的,就是在页面关闭后数据也能使用。

存储key-value数据。

代码实现:
setting.domStorageEnabled = true

4.Web Sql Database

原理是基于SQL的数据库存储一些结构性的数据,可以方便对数据进行增删改查。

代码实现:
setting.databaseEnabled = true
val path = "..."
setting.databasePath = path
这种方式官方已经不推荐使用了,后续版本不再维护。

5.Indexed Database缓存机制

这种方式取代了上面的方式。它是一种NoSql数据库,使用key-value的存储方式。

默认推荐250M。比较适合复杂,大量的结构化数据存储。

代码实现:
setting.javaScriptEnabled = true

 

缓存模式

1. LOAD_CACHE_ONLY:不使用网络,只读取本地缓存数据

2. LOAD_NO_CACHE:不使用缓存,只从网络获取数据

3. LOAD_DEFAULT:默认。根据cache-control决定是否从网络上获取数据

4.LOAD_CACHE_ELSE_NETWORK:只要本地有,无论是否过期,或者no-cache,都使用缓存中的数据。

setting.cacheMode = WebSettings.LOAD_CACHE_ELSE_NETWORK

 

使用总结:

1.存储静态资源文件,比如js,css,字体等。可以使用浏览器缓存,AppCache

2.存储临时数据可以使用 Dom Storage

3.存储复杂大量数据 可以使用Indexed Database

 

清除缓存:

//清空所有Cookie
CookieSyncManager.createInstance(getApplicationContext());  //Create a singleton CookieSyncManager within a context
CookieManager cookieManager = CookieManager.getInstance(); // the singleton CookieManager instance
cookieManager.removeAllCookie();// Removes all cookies.
CookieSyncManager.getInstance().sync(); // forces sync manager to sync now
 
mWebView.setWebChromeClient(null);
mWebView.setWebViewClient(null);
mWebView.getSettings().setJavaScriptEnabled(false);
mWebView.clearCache(true);
WebStorage.getInstance().deleteAllData();

 

 

四.Webview优化

1.加载速度优化

   1.1 Webview初始化

    webview首次创建的时间会比后续创建的时间要长很多。

    解决的办法是:创建一个全局Webview。在客户端开始启动时,就初始化一个全局的webview。

    当用户访问webview时,直接使用这个webview加载对应网页并展示。

    在application中创建一个webview:

class KotlinApplication:Application() {
    
    override fun onCreate() {
        super.onCreate()
        instance = this
        webView = WebView(this)
    }
    
    companion object {
        var instance: KotlinApplication by Delegates.notNull()
        lateinit var webView:WebView
    }
}

   在activity中使用:

    lateinit var layout:LinearLayout
    lateinit var web:WebView

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_second)
        layout = findViewById(R.id.layout_web)
        val lp = ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,ViewGroup.LayoutParams.MATCH_PARENT)
        web = KotlinApplication.webView
        web.layoutParams = lp
        layout.addView(web)

    这种方式缺点:消耗内存,实现webview进程独立很麻烦。

   

   1.2 预加载H5资源

     在应用启动时初始化第一个webview对象并直接加载H5页面(开启缓存)。

     后续需要打开这些H5页面时就直接从该本地对象中获取。

   1.3 页面加载和渲染

    延迟图片的加载,先加载并展示非图片内容

    用到的方法是:setBlockNetworkImage(Boolean)

override fun onPageStarted(view: WebView?, url: String?, favicon: Bitmap?) {
                super.onPageStarted(view, url, favicon)
                web.settings.blockNetworkImage = true
            }

            override fun onPageFinished(view: WebView?, url: String?) {
                super.onPageFinished(view, url)
                web.settings.blockNetworkImage = false
                if (!web.settings.loadsImagesAutomatically) {
                    //设置wenView加载图片资源
                    web.settings.blockNetworkImage = false
                    web.settings.loadsImagesAutomatically = true
                }
            }

2.内存优化

将webview所在的页面设置为另一个进程。

有效增大app的内存,减少由webview引起的内存泄露对主进程内存的占用

避免webview的crash影响app主进程的运行。

 

后续.....................................................

 

 

 

 

 

 

 

你可能感兴趣的:(Android)