打开一个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);
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就是第二参数传入的值。
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();
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主进程的运行。
后续.....................................................