日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > Android >内容正文

Android

android 加载条封装,Android基于JsBridge封装的高效带加载进度的WebView

發布時間:2024/1/23 Android 23 豆豆
生活随笔 收集整理的這篇文章主要介紹了 android 加载条封装,Android基于JsBridge封装的高效带加载进度的WebView 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

圖片發自簡書App

概述

從去年4月項目就一直用起了JsBridge,前面也針對jsBridge使用姿勢介紹過一篇入門篇,《Android JsBridge實戰 打造專屬你的Hybrid APP》,本篇接著繼續深入,通過再次優化封裝,大大優化了部分代碼,簡化上層調用流程,快速部署你的Hybridge APP。

再進行具體編碼前 ,我先進行了一般商業APP對WebView的需求

可加載本地和云端H5

擁有cookie持久能力

添加公共參數

回退前進功能

Js與本地navtive交互

擁有加載默認錯誤頁面能力

加載網頁可展現進度

好為了滿足以上常用功能,大致對webview相關知識進行下普及。

WebView

谷歌提供的系統組件,用來加載和展現html網頁,其采用webkit內核驅動,來實現網頁瀏覽功能。

擁有load() URL和本地html文件

// 云端

webView.loadUrl("https://www.baidu.com");

// 本地

webView.loadUrl("file:///android_asset/demo.html");

WebViewClient

WebViewClient主要輔助WebView執行處理各種響應請求事件的,比如:

onLoadResource

onPageStart

onPageFinish

onReceiveError

onReceivedHttpAuthRequest

shouldOverrideUrlLoading

本次加載失敗頁面,和攔截加入header頭必須用到它,由于android無法攔截h5本身ajax的請求,所以對header同步不是很好,建議大家對于ajax請求采用cookie形式,以防止url參數服務端無法獲取的問題。

加入header 一般直接使用webView.load(url, header)

view.loadUrl(url, header);

為了方便上層開發者調用,可以將此code加入到WebViewClient 的shouldOverrideUrlLoading中執行

姿勢那就是這樣:

public boolean shouldOverrideUrlLoading(WebView view, String url) {

if(this.onPageHeaders(url) != null) {

view.loadUrl(url, this.onPageHeaders(url));

}

return super.shouldOverrideUrlLoading(view, url);

}

錯誤頁面也是復寫WebViewClient的onReceivedError() 來加入自定義的抽象onPageError(),姿勢如下:

public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {

view.loadUrl(this.onPageError(failingUrl));

}

onPageHeaders()便是上層抽象出來的接口,方便我們直接加入header,而onPageError()是方便指定加載錯誤頁面,那么在activity中就是這樣了,

mProgressBarWebView.setWebViewClient(new CustomWebViewClient(mProgressBarWebView.getWebView()) {

@Override

public String onPageError(String url) {

return "file:///android_asset/error.html";

}

@Override

public Map onPageHeaders(String url) {

return CookieManger.getHeader(getContext());

}

});

WebChromeClient

主要輔助WebView處理Javascript的對話框、網站Logo、網站title、load進度等處理。

onCloseWindow(關閉WebView)

onCreateWindow()

onJsAlert ()

onJsPrompt

onJsConfirm

onProgressChanged

onReceivedIcon

onReceivedTitle

onShowCustomView

WebView只是用來處理一些html的頁面內容,只用WebViewClient就行了,如果需要更豐富的處理效果,比如JS、進度條等,就要用到WebChromeClient。因為這次功能要用加載進度,不得不說它。

為了加入頂部的加載進度條,復寫WebChromeClient中onProgressChanged,在這里更改我們加入的ProgressBar的進度,你也可以設置網頁標題,甚至可以全屏!

public class CustomWebChromeClient extends WebChromeClient {

private NumberProgressBar mProgressBar;

public CustomWebChromeClient(NumberProgressBar progressBar) {

this.mProgressBar = progressBar;

}

public void onProgressChanged(WebView view, int newProgress) {

if(newProgress >= 95) {

this.mProgressBar.setVisibility(8);

} else {

if(this.mProgressBar.getVisibility() == 8) {

this.mProgressBar.setVisibility(0);

}

this.mProgressBar.setProgress(newProgress);

}

super.onProgressChanged(view, newProgress);

}

//獲取tittle

@Override

public void onReceivedTitle(WebView view, String title) {

super.onReceivedTitle(view, title);

}

//全屏

@Override

public void onShowCustomView(View view, CustomViewCallback callback) {

super.onShowCustomView(view, callback);

}

}

好了準備好了同步Header和進度條之后,就的考慮cookie同步問題

CookieSync

CookieManager

CookieManager是用來管理Cookie的,主要來管理cookie相關,提供如下API

setAcceptCookie()

setCookie()

getCookie(String url);

removeSessionCookies();

hasCookies()

removeAllCookie()

CookieSyncManager

CookieSyncManagerl繼承WebSyncManager,來管理同步cookie相關,主要有以下API

resetSync()

stopSync()

sync()

syncFromRamToFlash()

checkInstanceIsAllowed()

Https

private class SSLTolerentWebViewClient extends WebViewClient {

public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {

handler.proceed(); // Ignore SSL certificate errors

}

}

你想問這些api什么意思,請保留點你的童真,不要問這么簡單的問題好嗎?

接著我們就可以這樣操作來實現cookie同步了,

CookieManager cookieManager = CookieManager.getInstance();

// 接受服務器cookie

cookieManager.setAcceptCookie(true);

//移除之前的cookie

cookieManager.removeSessionCookie();

// 注入cookies

List cookies = getCookies(customCookies);

for (String cookie : cookies) {

cookieManager.setCookie(uri.getHost(), cookie);

}

// 同步cookie

CookieSyncManager.getInstance().sync();

這里需要注意棒棒糖以上的會出現無法同步問題那么請這樣做

if ( Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {

cookieManager.flush();

} else {

CookieSyncManager.getInstance().sync();

}

經測試,完美!

你可能想問?我想自定義像header一樣加入一些自定義cookie,行,沒問題,繼續看!

public static List createCustomCookies() {

List cookies = new ArrayList<>();

cookies.add(“author ” + "= " + "tamic");

cookies.add(“data” + "= " + "2016.8.15");

cookies.add(“key” + "= " + 4fdfsfd34dfdfswer");

cookies.add(“chanel” + "= " + "簡書");

return cookies;

}

很可能會遇到處理緩存問題,設置緩存webView緩存模式!這里在普及下相關姿勢!

緩存模式

webview緩存模式有5種,具體方式:

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,都使用緩存中的數據。

www.baidu.com的cache-control為no-cache,在模式LOAD_DEFAULT下,無論如何都會從網絡上取數據,如果沒有網絡,就會出現錯誤頁面;在LOAD_CACHE_ELSE_NETWORK模式下,無論是否有網,只要本地有緩存,都會加載緩存。本地沒有緩存時才從網絡上獲取,

這個和Http緩存一致,我不在過多介紹,如果你想自定義緩存策略和時間,可以嘗試下,

清除緩存

CacheManager來處理webview緩存相關:

clearCache(boolean)

CacheManager.clear

在4.4以上的此api已經無法使用,也就是說緩存清空涉及安全,需要你自己去實現,就類似picasso, okhttp緩存,一樣要開發者自我去實現。

當然也可以這樣:

WebView.clearCache(true);

清空歷史記錄

mWebview.clearHistory();

需要在onPageFinished()的方法之后調用

ProgressBarWebView

學習了上面基礎知識,我這里就開始進行自定義的進度條ProgressBarWebView的封裝了,這里我直接對BridgeWebView進行擴展。下面是主要部分。

public class ProgressBarWebView extends LinearLayout {

static final String TAG = ProgressBarWebView.class.getSimpleName();

private NumberProgressBar mProgressBar;

private BridgeWebView mWebView;

public ProgressBarWebView(Context context) {

super(context);

this.init(context, (AttributeSet)null);

}

public ProgressBarWebView(Context context, AttributeSet attrs) {

super(context, attrs);

this.init(context, attrs);

}

@TargetApi(11)

public ProgressBarWebView(Context context, AttributeSet attrs, int defStyleAttr) {

super(context, attrs, defStyleAttr);

this.init(context, attrs);

}

@TargetApi(21)

public ProgressBarWebView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {

super(context, attrs, defStyleAttr, defStyleRes);

this.init(context, attrs);

}

為了使webview能有后退功能!我屏蔽了長按事件,并且對返回鍵建進行了攔截。

mWebView.setOnLongClickListener(new OnLongClickListener() {

public boolean onLongClick(View v) {

return true;

}

});

this.mWebView.setOnKeyListener(new OnKeyListener() {

public boolean onKey(View v, int keyCode, KeyEvent event) {

if(event.getAction() == 0 && keyCode == 4 && ProgressBarWebView.this.mWebView.canGoBack()) {

ProgressBarWebView.this.mWebView.goBack();

return true;

} else {

return false;

}

}

});

如果防止webview代碼產生內存泄漏,請及時在activity銷毀時,清空webview

@Override

public void onDestroy() {

super.onDestroyView();

if (mProgressBarWebView.getWebView() != null) {

mProgressBarWebView.getWebView().destroy();

}

}

看了構造方法你已明白,里面包含一個BridgeWebView和一個NumberProgressBar 成員屬性,

接著就是對JsBridge進行封裝了

js調用Java

public void registerHandler(final String handlerName, final JsHandler handler) {

this.mWebView.registerHandler(handlerName, new BridgeHandler() {

public void handler(String data, CallBackFunction function) {

if(handler != null) {

handler.OnHandler(handlerName, data, function);

// data實際就是js返回的jsonString數據,本案例為了統一處理,data統一采用{code,msg ,data} 形式,

}

}

});

}

Java調用js代碼:

public void callHandler(final String handlerName, String javaData, final JavaCallHandler handler) {

this.mWebView.callHandler(handlerName, javaData, new CallBackFunction() {

public void onCallBack(String data) {

if(handler != null) {

handler.OnHandler(handlerName, data);

}

}

});

}

看可jsBridge的可能問這個JsHandler誰神馬。本來在jsBridge源碼中沒這個東東的, 是為了方便上層調用我自己封裝的接口,

public interface JsHandler {

void OnHandler(String var1, String var2, CallBackFunction var3);

好了 關鍵的東西已經介紹完,如果對jsBridge可以看看去年我寫的一篇對他的介紹:Android JsBridge實戰 打造專屬你的Hybrid APP,

接著使用我們封裝好的ProgressBarWebView

案列使用

Dependencies

Gradle:

root:

repositories {

maven { url "https://jitpack.io" }

jcenter()

}

Module:

dependencies {

.....

compile 'com.tamic:browse:1.0.0'

}

初始化

ProgressBarWebView mProgressBarWebView = (ProgressBarWebView) findViewById(R.id.login_progress_webview);

設置自定義WebViewClient

mProgressBarWebView.setWebViewClient(new CustomWebViewClient(mProgressBarWebView.getWebView()) {

@Override

public String onPageError(String url) {

//指定網絡加載失敗時的錯誤頁面

return "file:///android_asset/error.html";

}

@Override

public Map onPageHeaders(String url) {

// 可以加入header

return null;

}

});

加載指定Url

mProgressBarWebView.loadUrl("file:///android_asset/demo.html");

當然,也可以支持網絡url;

注冊Js回調函數

ArrayList mHandlerNames = new ArrayList<>();

mHandlers.add("login");

mHandlers.add("callNative");

mHandlers.add("callJs");

mHandlers.add("open");

回調js的方法

mProgressBarWebView.registerHandlers(mHandlers, new JsHandler() {

@Override

public void OnHandler(String handlerName, String responseData, CallBackFunction function) {

if (handlerName.equals("login")) {

Toast.makeText(MainActivity.this, responseData, Toast.LENGTH_SHORT).show();

} else if (handlerName.equals("callNative")) {

Toast.makeText(MainActivity.this, responseData, Toast.LENGTH_SHORT).show();

function.onCallBack("我在上海");

} else if (handlerName.equals("callJs")) {

Toast.makeText(MainActivity.this, responseData, Toast.LENGTH_SHORT).show();

// 想調用你的方法:

function.onCallBack("好的 這是圖片地址 :xxxxxxx");

} if (handlerName.equals("open")) {

mfunction = function;

pickFile();

}

}

});

Native調用js

mProgressBarWebView.callHandler("callNative", "hello H5, 我是java", new JavaCallHandler() {

@Override

public void OnHandler(String handlerName, String jsResponseData) {

Toast.makeText(MainActivity.this, "h5返回的數據:" + jsResponseData, Toast.LENGTH_SHORT).show();

}

});

Native發送消息給js

mProgressBarWebView.send("哈嘍", new CallBackFunction() {

@Override

public void onCallBack(String data) {

Toast.makeText(MainActivity.this, data, Toast.LENGTH_SHORT).show();

}

});

}

Xml文件和js代碼這里不做介紹,具體看項目案列中源碼:

如果喜歡,請star!

效果圖:

圖片發自簡書App

結束語

這里感謝曾技術經理出身的同事的對相關部分代碼的封裝,感謝振南同學!

總結

以上是生活随笔為你收集整理的android 加载条封装,Android基于JsBridge封装的高效带加载进度的WebView的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。