| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> 系统运维 -> Android如何设计一个H5容器 -> 正文阅读 |
|
[系统运维]Android如何设计一个H5容器 |
APP端使用WebView的场景主要是加载H5页面、富文本展示和编辑、图表库(echart)等。当业务对APP动态化有相应需求时,H5作为一个老牌跨平台技术,是最常用的动态化技术之一。本文对WebView的技术需求和使用场景进行了整理,其中大部分是本人工作中遇到过的,部分是在查阅资料过程中发现的,希望对今后的开发有所帮助。 先来谈一谈H5容器的设计目标:
本文将围绕这些目标展开,结合WebView的基本用法介绍,力求尽量全面地了解WebView的使用。 WebView基本用法WebView
生命周期相关接口初始化:
前台:
后台:
销毁:
加载数据
页面导航
其他接口
Tricks浏览器用户认证
使用webview访问:
或使用webview WebViewClient回调:
或将用户名密码拼接到url进行访问,类似curl:
参考资料:Using WebView setHttpAuthUsernamePassword? WebSettingsAPI
Sets whether the WebView should support zooming using its on-screen zoom controls and gestures. The particular zoom mechanisms that should be used can be set with setBuiltInZoomControls. This setting does not affect zooming performed using the WebView.zoomIn() and WebView.zoomOut() methods. The default is true. Params:
Sets whether the WebView requires a user gesture to play media. The default is true. Params:
Sets whether the WebView should use its built-in zoom mechanisms. The built-in zoom mechanisms comprise on-screen zoom controls, which are displayed over the WebView’s content, and the use of a pinch gesture to control zooming. Whether or not these on-screen controls are displayed can be set with setDisplayZoomControls. The default is false. Params:
Sets whether the WebView should display on-screen zoom controls when using the built-in zoom mechanisms. See setBuiltInZoomControls. The default is true. Params:
Enables or disables file access within WebView. File access is enabled by default. Note that this enables or disables file system access only. Assets and resources are still accessible using file:///android_asset and file:///android_res.
Enables or disables content URL access within WebView. Content URL access allows WebView to load content from a content provider installed in the system. The default is enabled.
Sets whether JavaScript running in the context of a file scheme URL should be allowed to access content from any origin. This includes access to content from other file scheme URLs. See setAllowFileAccessFromFileURLs. To enable the most restrictive, and therefore secure policy, this setting should be disabled. Note that this setting affects only JavaScript access to file scheme resources. Other access to such resources, for example, from image HTML elements, is unaffected. To prevent possible violation of same domain policy on android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH and earlier devices, you should explicitly set this value to false. Params:
Sets whether the WebView should load image resources. Note that this method controls loading of all images, including those embedded using the data URI scheme. Use setBlockNetworkImage to control loading only of images specified using network URI schemes. Note that if the value of this setting is changed from false to true, all images resources referenced by content currently displayed by the WebView are loaded automatically. The default is true. Params:
Sets whether the WebView should not load image resources from the network (resources accessed via http and https URI schemes). Note that this method has no effect unless getLoadsImagesAutomatically returns true. Also note that disabling all network loads using setBlockNetworkLoads will also prevent network images from loading, even if this flag is set to false. When the value of this setting is changed from true to false, network images resources referenced by content currently displayed by the WebView are fetched automatically. The default is false. Params:
Sets whether the WebView should not load resources from the network. Use setBlockNetworkImage to only avoid loading image resources. Note that if the value of this setting is changed from true to false, network resources referenced by content currently displayed by the WebView are not fetched until WebView.reload is called. If the application does not have the android.Manifest.permission.INTERNET permission, attempts to set a value of false will cause a SecurityException to be thrown. The default value is false if the application has the android.Manifest.permission.INTERNET permission, otherwise it is true. Params:
Sets whether the WebView loads pages in overview mode, that is, zooms out the content to fit on screen by width. This setting is taken into account when the content width is greater than the width of the WebView control, for example, when getUseWideViewPort is enabled. The default is false.
Sets whether the WebView should save form data. The default is true.
Sets the text zoom of the page in percent. The default is 100.
Sets policy for third party cookies. Developers should access this via CookieManager.setShouldAcceptThirdPartyCookies.
Sets whether the WebView should enable support for the “viewport” HTML meta tag or should use a wide viewport. When the value of the setting is false, the layout width is always set to the width of the WebView control in device-independent (CSS) pixels. When the value is true and the page contains the viewport meta tag, the value of the width specified in the tag is used. If the page does not contain the tag or does not provide a width, then a wide viewport will be used. Params:
Sets whether the WebView whether supports multiple windows. If set to true, WebChromeClient.onCreateWindow must be implemented by the host application. The default is false. Params:
Tells JavaScript to open windows automatically. This applies to the JavaScript function window.open(). The default is false. Params:
Sets the underlying layout algorithm. This will cause a relayout of the WebView. The default is WebSettings.LayoutAlgorithm.NARROW_COLUMNS. Params:
Sets the standard font family name. The default is “sans-serif”. Params:
Sets the fixed font family name. The default is “monospace”. Params:
Sets the sans-serif font family name. The default is “sans-serif”. Params:
Params:
Sets the cursive font family name. The default is “cursive”. Params:
Sets the fantasy font family name. The default is “fantasy”. Params:
Sets the minimum font size. The default is 8. Params:
Sets the minimum logical font size. The default is 8. Params:
Sets the default font size. The default is 16. Params:
Sets the default fixed font size. The default is 16. Params:
Tells the WebView to enable JavaScript execution. The default is false. Params:
Sets the path where the Geolocation databases should be saved. In order for Geolocation permissions and cached positions to be persisted, this method must be called with a path to which the application can write. Params:
Sets whether the Application Caches API should be enabled. The default is false. Note that in order for the Application Caches API to be enabled, a valid database path must also be supplied to setAppCachePath. Params:
Sets the path to the Application Caches files. In order for the Application Caches API to be enabled, this method must be called with a path to which the application can write. This method should only be called once: repeated calls are ignored. Params:
Sets whether the database storage API is enabled. The default value is false. See also setDatabasePath for how to correctly set up the database storage API. This setting is global in effect, across all WebView instances in a process. Note you should only modify this setting prior to making any WebView page load within a given process, as the WebView implementation may ignore changes to this setting after that point. Params:
Sets whether the DOM storage API is enabled. The default value is false. Params:
Sets whether Geolocation is enabled. The default is true. Params:
Sets the default text encoding name to use when decoding html pages. The default is “UTF-8”. Params:
Sets the WebView’s user-agent string. If the string is null or empty, the system default value will be used. Note that starting from android.os.Build.VERSION_CODES.KITKAT Android version, changing the user-agent while loading a web page causes WebView to initiate loading once again. Params:
Tells the WebView whether it needs to set a node to have focus when WebView.requestFocus(int, android.graphics.Rect) is called. The default value is true. Params:
Params:
Params:
Sets whether this WebView should raster tiles when it is offscreen but attached to a window. Turning this on can avoid rendering artifacts when animating an offscreen WebView on-screen. Offscreen WebViews in this mode use more memory. The default value is false. Please follow these guidelines to limit memory usage: Tricks常用移动端H5设置
缓存模式
如:www.taobao.com的cache-control为no-cache,在模式LOAD_DEFAULT下,无论如何都会从网络上取数据,如果没有网络,就会出现错误页面;在LOAD_CACHE_ELSE_NETWORK模式下,无论是否有网络,只要本地有缓存,都使用缓存。本地没有缓存时才从网络上获取。
WebViewClientAPI
Give the host application a chance to take over the control when a new url is about to be loaded in the current WebView. If WebViewClient is not provided, by default WebView will ask Activity Manager to choose the proper handler for the url. If WebViewClient is provided, return true means the host application handles the url, while return false means the current WebView handles the url. This method is not called for requests using the POST “method”. Params:
Notify the host application that a page has started loading. This method is called once for each main frame load so a page with iframes or framesets will call onPageStarted one time for the main frame. This also means that onPageStarted will not be called when the contents of an embedded frame changes, i.e. clicking a link whose target is an iframe, it will also not be called for fragment navigations (navigations to #fragment_id). Params:
Notify the host application that a page has finished loading. This method is called only for main frame. When onPageFinished() is called, the rendering picture may not be updated yet. To get the notification for the new Picture, use WebView.PictureListener.onNewPicture. Params:
Notify the host application that the WebView will load the resource specified by the given url. Params:
Notify the host application that WebView content left over from previous page navigations will no longer be drawn. Params:
Notify the host application of a resource request and allow the application to return the data. If the return value is null, the WebView will continue to load the resource as usual. Otherwise, the return response and data will be used. NOTE: This method is called on a thread other than the UI thread so clients should exercise caution when accessing private data or the view system. Params:
Params:
Notify the host application that an HTTP error has been received from the server while loading a resource. HTTP errors have status codes >= 400. This callback will be called for any resource (iframe, image, etc), not just for the main page. Thus, it is recommended to perform minimum required work in this callback. Note that the content of the server response may not be provided within the errorResponse parameter. Params:
Notify the host application that an SSL error occurred while loading a resource. The host application must call either handler.cancel() or handler.proceed(). Note that the decision may be retained for use in response to future SSL errors. The default behavior is to cancel the load. Params:
As the host application if the browser should resend data as the requested page was a result of a POST. The default is to not resend the data. Params:
Notify the host application to update its visited links database. Params:
Notify the host application to handle a SSL client certificate request. The host application is responsible for showing the UI if desired and providing the keys. There are three ways to respond: proceed(), cancel() or ignore(). Webview stores the response in memory (for the life of the application) if proceed() or cancel() is called and does not call onReceivedClientCertRequest() again for the same host and port pair. Webview does not store the response if ignore() is called. This method is called on the UI thread. During the callback, the connection is suspended. For most use cases, the application program should implement the android.security.KeyChainAliasCallback interface and pass it to android.security.KeyChain.choosePrivateKeyAlias to start an activity for the user to choose the proper alias. The keychain activity will provide the alias through the callback method in the implemented interface. Next the application should create an async task to call android.security.KeyChain.getPrivateKey to receive the key. An example implementation of client certificates can be seen at AOSP Browser The default behavior is to cancel, returning no client certificate. Params:
Notifies the host application that the WebView received an HTTP authentication request. The host application can use the supplied HttpAuthHandler to set the WebView’s response to the request. The default behavior is to cancel the request. Params:
Notify the host application that a request to automatically log in the user has been processed. Params:
Give the host application a chance to handle the key event synchronously. e.g. menu shortcut key events need to be filtered this way. If return true, WebView will not handle the key event. If return false, WebView will always handle the key event, so none of the super in the view chain will see the key event. The default behavior returns false. Params:
Notify the host application that a input event was not handled by the WebView. Except system keys, WebView always consumes input events in the normal flow or if shouldOverrideKeyEvent returns true. This is called asynchronously from where the event is dispatched. It gives the host application a chance to handle the unhandled input events. Note that if the event is a android.view.MotionEvent, then it’s lifetime is only that of the function call. If the WebViewClient wishes to use the event beyond that, then it must create a copy of the event. It is the responsibility of overriders of this method to call onUnhandledKeyEvent(WebView, KeyEvent) when appropriate if they wish to continue receiving events through it. Params:
Notify the host application that the scale applied to the WebView has changed. Params: Tricks高频拦截接口
WebChromeClientAPI
Tell the host application the current progress of loading a page. Params:
Notify the host application of a change in the document title. Params:
Notify the host application of a new favicon for the current page. Params:
Notify the host application of the url for an apple-touch-icon. Params:
Notify the host application that the current page has entered full screen mode. The host application must show the custom View which contains the web contents — video or other HTML content — in full screen mode. Also see “Full screen support” documentation on WebView. Params:
Notify the host application that the current page has exited full screen mode. The host application must hide the custom View, ie. the View passed to onShowCustomView when the content entered fullscreen. Also see “Full screen support” documentation on WebView.
Request the host application to create a new window. If the host application chooses to honor this request, it should return true from this method, create a new WebView to host the window, insert it into the View system and send the supplied resultMsg message to its target with the new WebView as an argument. If the host application chooses not to honor the request, it should return false from this method. The default implementation of this method does nothing and hence returns false. Params:
Notify the host application to close the given WebView and remove it from the view system if necessary. At this point, WebCore has stopped any loading in this window and has removed any cross-scripting ability in javascript. Params:
Request display and focus for this WebView. This may happen due to another WebView opening a link in this WebView and requesting that this WebView be displayed. Params:
Tell the client to display a javascript alert dialog. If the client returns true, WebView will assume that the client will handle the dialog. If the client returns false, it will continue execution. Params:
Tell the client to display a confirm dialog to the user. If the client returns true, WebView will assume that the client will handle the confirm dialog and call the appropriate JsResult method. If the client returns false, a default value of false will be returned to javascript. The default behavior is to return false. Params:
Tell the client to display a prompt dialog to the user. If the client returns true, WebView will assume that the client will handle the prompt dialog and call the appropriate JsPromptResult method. If the client returns false, a default value of false will be returned to to javascript. The default behavior is to return false. Params:
Tell the client to display a dialog to confirm navigation away from the current page. This is the result of the onbeforeunload javascript event. If the client returns true, WebView will assume that the client will handle the confirm dialog and call the appropriate JsResult method. If the client returns false, a default value of true will be returned to javascript to accept navigation away from the current page. The default behavior is to return false. Setting the JsResult to true will navigate away from the current page, false will cancel the navigation. Params:
Notify the host application that web content from the specified origin is attempting to use the Geolocation API, but no permission state is currently set for that origin. The host application should invoke the specified callback with the desired permission state. See GeolocationPermissions for details. Params:
Notify the host application that a request for Geolocation permissions, made with a previous call to onGeolocationPermissionsShowPrompt() has been canceled. Any related UI should therefore be hidden.
Notify the host application that web content is requesting permission to access the specified resources and the permission currently isn’t granted or denied. The host application must invoke PermissionRequest.grant(String[]) or PermissionRequest.deny(). If this method isn’t overridden, the permission is denied. Params:
Notify the host application that the given permission request has been canceled. Any related UI should therefore be hidden. Params:
Report a JavaScript console message to the host application. The ChromeClient should override this to process the log message as they see fit. Params:
When not playing, video elements are represented by a ‘poster’ image. The image to use can be specified by the poster attribute of the video tag in HTML. If the attribute is absent, then a default poster will be used. This method allows the ChromeClient to provide that default image. Returns:
Obtains a View to be displayed while buffering of full screen video is taking place. The host application can override this method to provide a View containing a spinner or similar. Returns:
Obtains a list of all visited history items, used for link coloring
Tell the client to show a file chooser. This is called to handle HTML forms with ‘file’ input type, in response to the user pressing the “Select File” button. To cancel the request, call filePathCallback.onReceiveValue(null) and return true. Params: Tricks
|
服务端header | 说明 | 客户端header | 说明 |
---|---|---|---|
Expires | 缓存过期的日期和时间,给客户端用 | 无 | 当有缓存时判断缓存是否过期 |
Cache-Control | 设置和缓存相关的配置信息,Cache-Control也可以返回一个过期时间,其功能比Expires更丰富,且优先级更高 | 无 | 配合Expires的值,判断缓存是否过期 |
Last-Modified | 请求资源最后修改时间 | If-Modified-SInce | 客户端回传Last-Modified给服务器,服务器判断资源是否有更新,无更新返回304,减少网络数据传输 |
ETag | 请求变量的实体标签的当前值,比如文件的MD5值 | If-None-Match | 客户端回传ETag,服务端判断资源有更新 |
补充:浏览器在得到服务端返回的资源时还会根据Cache-Control指定的规则以及浏览器是否开启缓存功能来确定是否缓存。
1、可以在html页面中添加 来给页面设置缓存时间。
2、对于图片、css等文件则需要web服务器配置中进行规则配置实现在请求资源的时候添加在responese的header中。
Dom Storage 提供 5MB 大小的缓存空间,以键值对的形式存取文件。
H5 提供了基于 SQL 的数据库存储机制,用于存储一些结构化的数据。
Application Cache(简称 AppCache)似乎是为支持 Web App 离线使用而开发的缓存机制。它的缓存机制类似于浏览器的缓存(Cache-Control 和 Last-Modified)机制,都是以文件为单位进行缓存,且文件有一定更新机制。AppCache 是对浏览器缓存机制的补充,不是替代。不过根据官方文档,AppCache 已经不推荐使用了,标准也不会再支持。现在主流的浏览器都是还支持AppCache的。
IndexedDB 也是一种数据库的存储机制,但不同于已经不再支持的 Web SQL Database。IndexedDB 不是传统的关系数据库,可归为 NoSQL 数据库。IndexedDB 又类似于 Dom Storage 的 key-value 的存储方式,但功能更强大,且存储空间更大。Android 在4.4开始加入对 IndexedDB 的支持,只需打开允许 JS 执行的开关就好了。
File System API 是 H5 新加入的存储机制。它为 Web App 提供了一个虚拟的文件系统,就像 Native App 访问本地文件系统一样。由于安全性的考虑,这个虚拟文件系统有一定的限制。Web App 在虚拟的文件系统中,可以进行文件(夹)的创建、读、写、删除、遍历等操作。很可惜到目前,Android 系统的 WebView 还不支持 File System API。
// 开启Dom Storage(Web Storage)存储机制,默认false
webSettings.setDomStorageEnabled(true);
// 开启Web SQL Database存储机制,默认false,虽然已经不推荐使用了,但是为了兼容性还是开启下
webSettings.setDatabaseEnabled(true);
webSettings.setDatabasePath(getDir("db",Context.MODE_PRIVATE).getPath())
// 开启Application Cache存储机制
webSettings.setAppCacheEnabled(true);
webSettings.setAppCachePath(getDir("cache",Context.MODE_PRIVATE).getPath());
webSettings.setAppCacheMaxSize(5*1024*1024);
// 开启Indexed Database 存储机制,默认false
webSettings.setJavaScriptEnabled(true);
缓存优化可以加快webview二次启动的加载速度,那么首次加载该怎么优化呢?预加载资源就是一个比较好的方案,仅从资源下载的角度先分析一下一个H5网页的加载过程:
第一阶段和第二阶段是不能并行执行的,可以从这两点入手进行优化。
如果页面样式是相对固定的,可以和前端(如果和App不是同一个开发)探讨设计一个HTML/CSS/JS模板,然后动态变化的CSS/JS通过HTML模板进行解析下载,模板文件直接将模板打入安装包中,这个一步优化效果是立竿见影的,不仅将两阶段下载缩减为一个,同时由于通常HTML下载通常耗时占比也比较高,所以可以很直观感受到加载速度的加快,因为用户很快就可以看见一个界面,而不是等待loading。
当然更多的情况是前端和APP之间没有这样的协同开发机制或HTML为了实现动态更新,很难做到HTML本地化,那么可以退而求其次,把H5页面的通用方法封装成JS库打入App中,APP在WebView 调用了onPageFinished() 方法后进行加载。
示例:一个基本的html文件格式+原生端配合
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
<script type="text/javascript">
function show(jsondata){
//[{name:"xxx",amount:600,phone:"13988888"},{name:"bb",amount:200,phone:"1398788"}]
var jsonobjs = eval(jsondata);
var table = document.getElementById("personTable");
for(var y=0; y<jsonobjs.length; y++){
var tr = table.insertRow(table.rows.length); //添加一行
//添加三列
var td1 = tr.insertCell(0);
var td2 = tr.insertCell(1);
td2.align = "center";
var td3 = tr.insertCell(2);
td3.align = "center";
//设置列内容和属性
td1.innerHTML = jsonobjs[y].name;
td2.innerHTML = jsonobjs[y].amount;
td3.innerHTML = "<a href='javascript:contact.call(\""+ jsonobjs[y].phone+ "\")'>"+ jsonobjs[y].phone+ "</a>";
}
}
</script>
</head>
<!-- js代码通过webView调用其插件中的java代码,即 -->
<body onload="javascript:contact.showContacts()">
<table border="0" width="100%" id="personTable" cellspacing="0">
<tr>
<td width="35%">姓名</td><td width="30%" align="center">存款</td><td align="center">电话</td>
</tr>
</table>
<a href="javascript:window.location.reload()">刷新</a>
</body>
</html>
原生端代码:
public class MainActivity extends AppCompatActivity {
private WebView mWebView;
private Handler mHandler = new Handler();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mWebView = (WebView) findViewById(R.id.web_view);
mWebView.loadUrl("file:///android_asset/index.html");
mWebView.getSettings().setJavaScriptEnabled(true);
mWebView.addJavascriptInterface(new JSObject(),"contact");
}
public class JSObject{
@JavascriptInterface
public void call(String phone){
Log.e("phone", "phone---->" + phone);
}
@JavascriptInterface
public void showContacts(){
try {
JSONArray jsonArray = new JSONArray();
JSONObject jsonObject = new JSONObject();
jsonObject.put("name", "zhangsan");
jsonObject.put("amount", "50");
jsonObject.put("phone", "123465798");
jsonArray.put(jsonObject);
JSONObject jsonObject1 = new JSONObject();
jsonObject1.put("name", "lisi");
jsonObject1.put("amount", "48");
jsonObject1.put("phone", "987456123");
jsonArray.put(jsonObject1);
final String json = jsonArray.toString();
// 调用javascript中的show()方法
mHandler.post(new Runnable() {
@Override
public void run() {
mWebView.loadUrl("javascript:show('" + json + "')");
}
});
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
页面加载完成后,调用webView.loadUrl("javascript:"+jsContent)
进行JS注入。需要注意的是,在该 JS 文件中需要写入一个 JS 文件载入完毕的事件,这样前端才能接受都到 JS 文件已经种植完毕,可以调用 JS 中的方法了。
示例JS代码:
;
(function() {
try{
window.JSBridge = {
'invoke': function(name) {
var args = [].slice.call(arguments, 1),
callback = args.pop(),
params, obj = this[name];
if (typeof callback !== 'function') {
params = callback;
callback = function() {}
} else {
params = args[0]
} if (typeof obj !== 'object' || typeof obj.func !== 'function') {
callback({
'err_msg': 'system:function_not_exist'
});
return
}
obj.callback = callback;
obj.params = params;
obj.func(params)
},
'on': function(event, callback) {
var obj = this['on' + event];
if (typeof obj !== 'object') {
callback({
'err_msg': 'system:function_not_exist'
});
retrun
}
if (typeof callback !== 'undefined') obj.callback = callback
},
'login': {
'func': function(params) {
prompt("login", JSON.stringify(params))
},
'params': {},
'callback': function(res) {}
},
'settitle': {
'func': function(params) {
prompt("settitle",JSON.stringify(params))
},
'params': {},
'callback': function(res) {}
},
}catch(e){
alert('demo.js error:'+e);
}
var readyEvent = document.createEvent('Events');
readyEvent.initEvent('JSBridgeReady', true, true);
document.dispatchEvent(readyEvent)
})();
可以比较一下在onPageFinished() 注入JS和shouldInterceptRequest()中替换JS本地文件哪个更多,择优选择方案
关于JS延迟加载。Android 的 OnPageFinished 事件会在 Javascript 脚本执行完成之后才会触发。如果在页面中使 用JQuery,会在处理完 DOM 对象,执行完 $(document).ready(function() {}); 事件自会后才会渲染并显示页面。而同样的页面在 iPhone 上却是载入相当的快,因为 iPhone 是显示完页面才会触发脚本的执行。一种解决方案是延迟 JS 脚本的载入,这个方面的问题是需要Web前端工程师帮忙优化的。
WebView为我们提供了资源请求拦截回调,从而可以实现外部依赖的 JS、CSS、图片等资源提前下载好,等H5 加载时直接替换:
mWebView.setWebViewClient(new WebViewClient() {
@Override
public WebResourceResponse shouldInterceptRequest(WebView webView, final String url) {
WebResourceResponse response = null;
// 检查该资源是否已经提前下载完成。我采用的策略是在应用启动时,用户在 wifi 的网络环境下
// 提前下载 H5 页面需要的资源。
boolean resDown = JSHelper.isURLDownValid(url);
if (resDown) {
jsStr = JsjjJSHelper.getResInputStream(url);
if (url.endsWith(".png")) {
response = getWebResourceResponse(url, "image/png", ".png");
} else if (url.endsWith(".gif")) {
response = getWebResourceResponse(url, "image/gif", ".gif");
} else if (url.endsWith(".jpg")) {
response = getWebResourceResponse(url, "image/jepg", ".jpg");
} else if (url.endsWith(".jepg")) {
response = getWebResourceResponse(url, "image/jepg", ".jepg");
} else if (url.endsWith(".js") && jsStr != null) {
response = getWebResourceResponse("text/javascript", "UTF-8", ".js");
} else if (url.endsWith(".css") && jsStr != null) {
response = getWebResourceResponse("text/css", "UTF-8", ".css");
} else if (url.endsWith(".html") && jsStr != null) {
response = getWebResourceResponse("text/html", "UTF-8", ".html");
}
}
// 若 response 返回为 null , WebView 会自行请求网络加载资源。
return response;
}
});
private WebResourceResponse getWebResourceResponse(String url, String mime, String style) {
WebResourceResponse response = null;
try {
response = new WebResourceResponse(mime, "UTF-8", new FileInputStream(new File(getJSPath() + MD5.md5String(url) + style)));
} catch (FileNotFoundException e) {
e.printStackTrace();
}
return response;
}
public String getJSPath() {
String splashTargetPath = context.getFilesDir().getPath() + "/JS";
if (!FileUtil.isDirFileExist(splashTargetPath)) {
FileUtil.createDir(splashTargetPath);
}
return splashTargetPath + "/";
}
指降低图片下载优先级,是为了把带宽让步给JS/CSS,使页面框架先下载好渲染出来呈现给用户,缩短页面空白期的持续时间,而图片等可以后面逐步加载。
public void int () {
if(Build.VERSION.SDK_INT >= 19) {
webView.getSettings().setLoadsImagesAutomatically(true);
} else {
webView.getSettings().setLoadsImagesAutomatically(false);
}
}
//同时在WebView的WebViewClient实例中的onPageFinished()方法添加如下代码:
@Override
public void onPageFinished(WebView view, String url) {
if(!webView.getSettings().getLoadsImagesAutomatically()) {
webView.getSettings().setLoadsImagesAutomatically(true);
}
}
上面代码对系统API在19以上的版本作了兼容。因为4.4以上系统在onPageFinished时再恢复图片加载时,如果存在多张图片引用的是相同的src时,会只有一个image标签得到加载,因而对于这样的系统我们就先直接加载。
webview实例的创建需要占用大量内存(即使不加载任内容),而且即便销毁含有webview的页面,相关内存也无法被完全释放。关于webview内存泄漏的问题早在2009年就被人提出(链接),问题提到了泄漏的源头是PlguinManager持有了context引用,导致activity内存泄漏,但是采用applicationContext又会导致flash内容奔溃。
目前解决webview内存泄漏主要有三个方案:
使用独立进程的好处是,webview各种内存占用、泄漏甚至OOM的问题不会影响到主进程。WebView 开启独立进程的方法如下:
<activity
android:name=".ui.webview.CommWebviewActivity"
android:configChanges="orientation|keyboardHidden|screenSize"
android:process=":webview"
android:screenOrientation="portrait"
android:windowSoftInputMode="stateHidden">
<intent-filter>
<category android:name="android.intent.category.BROWSABLE" />
<category android:name="android.intent.category.DEFAULT" />
<action android:name="android.intent.action.VIEW" />
<data android:host="xxxx.com" android:scheme="myapp" />
</intent-filter>
</activity>
重点是android:process=":webview"
,后续通讯可以通过aidl实现,这里就不过多介绍了。
开启硬件加速后WebView渲染页面更加快速,拖动也更加顺滑。开启方法:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
webview.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
}
当WebView视图被整体遮住一块,然后突然恢复时(比如使用SlideMenu将WebView从侧边滑出来时),这个过渡期会出现白块同时界面闪烁。解决这个问题的方法是在过渡期前将WebView的硬件加速临时关闭,过渡期后再开启。
|
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2025年1日历 | -2025/1/8 5:43:34- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |