您的位置:首页 > 移动开发

WebView实战与设计

2016-04-02 16:06 399 查看

WebView实战与设计

1、简述

现在纯Native的应用越来越少,即使一个使用Native开发的应用,有些模块也需要用WebView加载h5页面,比如新年活动之类生命周期很短的模块,那么使用WebView+H5的模式开发将成为首选,一来可以节约成本,再者,h5页面可以频繁更改,非常适合做活动类的模块。当然hybrid应用中,WebView的使用更是频繁。

WebView是Android SDK中内置的一个控件,可以理解为内置的浏览器。

WebView:Android SDK中内置的一个控件,可以理解为浏览器。常用的API有:

加载一个页面:

/**
* Loads the given URL.
*
* @param url the URL of the resource to load
*/
public void loadUrl(String url) {
//
}
给Js注入对象,在注入对象中,可以写方法让Js调用Native的逻辑,实现Js与Native的交互:

/**
* Injects the supplied Java object into this WebView. The object is
* injected into the JavaScript context of the main frame, using the
* supplied name. This allows the Java object's methods to be
* accessed from JavaScript.
* @param object the Java object to inject into this WebView's JavaScript
*               context. Null values are ignored.
* @param name the name used to expose the object in JavaScript
*/
public void addJavascriptInterface(Object object, String name) {
//
}
设置WebViewClient:

/**
* Sets the WebViewClient that will receive various notifications and
* requests. This will replace the current handler.
*
* @param client an implementation of WebViewClient
*/
public void setWebViewClient(WebViewClient client) {
checkThread();
mProvider.setWebViewClient(client);
}
设置WebChromeClient:

/**
* Sets the chrome handler. This is an implementation of WebChromeClient for
* use in handling JavaScript dialogs, favicons, titles, and the progress.
* This will replace the current handler.
*
* @param client an implementation of WebChromeClient
*/
public void setWebChromeClient(WebChromeClient client) {
checkThread();
mProvider.setWebChromeClient(client);
}


CookieManager:WebView的Cookie管理类,可以把Native的登录态传给WebView,让H5页面也是登录态:

/**
* 设置Cookie
*/
private void setCookie4WebView() {
//获取Cookie
List<Cookie> cookies = NetUtil.getInstance().getCookieStore().getCookies();
if (cookies != null) {
//The CookieSyncManager is used to synchronize the browser cookie store
// between RAM and permanent storage. To get the best performance, browser cookies are
//saved in RAM. A separate thread saves the cookies between, driven by a timer.
CookieSyncManager.createInstance(this);
//Manages the cookies used by an application's {@link WebView} instances.
// Cookies are manipulated according to RFC2109.
CookieManager cookieManager = CookieManager.getInstance();
cookieManager.setAcceptCookie(true);
for (int i = 0; i < cookies.size(); i++) {
Cookie cookie = cookies.get(i);
String cookieString = cookie.getName() + "=" + cookie.getValue();
//Sets a cookie for the given URL. Any existing cookie with the same host,
//path and name will be replaced with the new cookie. The cookie being set
//will be ignored if it is expired.
cookieManager.setCookie(NetUrlConstant.Url_Base + "/", cookieString);
}
//sync() forces sync manager to sync now
CookieSyncManager.getInstance().sync();
}
}


WebChromeClient:主要辅助WebView处理JavaScript的对话框、网站图标、网站title、加载进度条等:

public class WebChromeClient extends android.webkit.WebChromeClient {
@Override
public void onProgressChanged(WebView view, int newProgress) {
//页面加载中进度条的变化
if (newProgress == 100) {
progressBar.setVisibility(View.GONE);
} else {
if (progressBar.getVisibility() == View.GONE)
progressBar.setVisibility(View.VISIBLE);
progressBar.setProgress(newProgress);
}
super.onProgressChanged(view, newProgress);
}


WebViewClient:主要帮助WebView处理各种通知、请求事件:

setWebChromeClient(new WebChromeClient() {
@Override
public void onReachedMaxAppCacheSize(long requiredStorage, long quota, WebStorage.QuotaUpdater quotaUpdater) {
quotaUpdater.updateQuota(requiredStorage * 2);
}
});

setWebViewClient(new WebViewClient() {

@Override
public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
handler.proceed();  // 接受所有网站的证书
}

@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
if (!url.contains("tel:")) {
if (url.contains(context.getPackageName())) {
view.loadUrl(url);
} else if (url.equals("local://redo")) {
if (!StringHelper.isEmpty(failUrl)) {
view.loadUrl(failUrl);
}
} else {
view.loadUrl("file:///android_asset/noWifi.html");
}
}
return true;
}

@Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
super.onPageStarted(view, url, favicon);
isLoad = false;
//                if (!url.contains("noWifi.html") && !url.contains("txt.pingan.com.cn")) {
//                    activity.showLoading(true);
//                }
if (!url.contains("http")) {
activity.showLoading(true);
}
}

@Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
//                if (url.contains("noWifi.html") || url.contains("fs-txt.pingan.com.cn")) {
//                    activity.showLoading(false);
//                }
if (url.contains("http")) {
activity.showLoading(false);
}
isLoad = true;
}

@Override
public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
//缓存错误页面
failUrl = failingUrl;
view.stopLoading();
view.clearView();
view.loadUrl("javascript:document.body.innerHTML=\"" + "" + "\"");
view.loadUrl("file:///android_asset/noWifi.html");
activity.showLoading(false);
super.onReceivedError(view, errorCode, description, failingUrl);
}
});


WebViewSetting:管理WebView的设置状态。官方介绍:

Manages settings state for a WebView. When a WebView is first created, it
* obtains a set of default settings. These default settings will be returned
* from any getter call. A WebSettings object obtained from
* WebView.getSettings() is tied to the life of the WebView.


webSettings = getSettings();
webSettings.setJavaScriptEnabled(true);//允许调用JavaScript
webSettings.setUseWideViewPort(true); //设置内容自适应屏幕大小
webSettings.setRenderPriority(WebSettings.RenderPriority.HIGH);//提高渲染的优先级
webSettings.setSupportZoom(false);//页面禁止缩放
webSettings.setDomStorageEnabled(true);//允许使用本地缓存

int sdk = Build.VERSION.SDK_INT;

if (sdk > 10) {
setLayerType(View.LAYER_TYPE_SOFTWARE, null);
}
webSettings.setCacheMode(WebSettings.LOAD_DEFAULT);
webSettings.setSaveFormData(true);
webSettings.setAppCacheMaxSize(1024 * 5);

//存储H5
String appCacheDir = context.getApplicationContext().getDir("cache", Context.MODE_PRIVATE).getPath() + APP_CACAHE_DIRNAME;
//        String appCacheDir = context.getFilesDir().getAbsolutePath() + APP_CACAHE_DIRNAME;
webSettings.setAppCachePath(appCacheDir);
webSettings.setAllowFileAccess(true);
webSettings.setAppCacheEnabled(true);

//       //存储url
webSettings.setDatabaseEnabled(true);
//        String appData = context.getApplicationContext().getDir("databases", Context.MODE_PRIVATE).getPath() + APP_DB_DIRNAME;
webSettings.setDatabasePath(appCacheDir);


WebViewJsInjection:Js注入类,该该类中,可以写方法给H5页面调用:

/**
* the Java object to inject into this WebView's JavaScript
*/
public class WebViewJS {

@JavascriptInterface
public void linkRecord(int recordid) {
//
}

@JavascriptInterface
public void linkThing(long thingid) {
//
}

@JavascriptInterface
public void linkUser(int userid) {
//
}

public void linkLogin(){
//
}
}


2、整体的设计:

废话不多说,先上UML类图:



WebApp1Activity:普通的Activity界面,放一个WebView,加载h5;

ProgresswebView:自定义的WebView,带进度条

MyWebChromeClient:自定义的WebChromeClient,处理页面变化过程中进度条的变化,需要风行Progressbar,作为ProgresswebView内部类出现

MyWebViewClient:自定义的WebViewClient,处理加载页面的相关事件

INativeJsInjection:Native给Js的注入类接口,抽象,让ProgressView依赖抽象,不依赖具体实现

DetailNativeJsInjection1:Native给Js注入类的具体实现

附:Github地址

参考:WebViewClient与WebChromeClient的区别
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息