天天看點

基于cordova實作的webview實作與h5的互動

該片文章講述項目中遇到的問題,以及相關優化細節。

一、項目背景

1、項目需要支援hybrid應用,是以部分提供h5調用的通用js儲存在用戶端本地。優點有:通路速度快和無需額外資料流量。

2、項目首頁都是h5形式,采用vue架構,支援離線緩存

3、使用CordovaWebView加載h5應用。

二、問題清單和優化

1、h5應用如何讀到本地js檔案?

針對第1個問題,很簡單解決。webview提供攔截方法,隻要和js端定義好import的格式,比對好即可。代碼編寫如下:

攔截方法入口,系統版本不一緻,調用方法不一樣,請知曉。

基于cordova實作的webview實作與h5的互動
/**
 * URL攔截請求方法(API21以上)
 * @param webView
 * @param webResourceRequest 請求資訊
 * @return
 */
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
@Override
public WebResourceResponse shouldInterceptRequest(WebView webView, WebResourceRequest webResourceRequest) {
    //21版本
    //通過版本控制來将2個入口引入到一個攔截方法中
    String method = webResourceRequest != null ? webResourceRequest.getMethod() : null;
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
        //OPTIONS請求跳過
        if (method != null && method.equalsIgnoreCase("OPTIONS")) {
            return null;
        }
        return customInterceptRequest(webView,
                webResourceRequest.getUrl().toString(),
                method,
                webResourceRequest.getRequestHeaders(),
                super.shouldInterceptRequest(webView, webResourceRequest));
    }
    return super.shouldInterceptRequest(webView, webResourceRequest);
}

/**
 * URL攔截請求方法(API21以下)
 * @param view
 * @param url 請求位址
 * @return
 */
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
@Override
public WebResourceResponse shouldInterceptRequest(WebView view, String url) {
    //11版本
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
        return customInterceptRequest(view, url, null, null, super.shouldInterceptRequest(view, url));
    }
    return super.shouldInterceptRequest(view, url);
}      

比對url,重新寫回WebResourceResponse

基于cordova實作的webview實作與h5的互動
/**
 * 加載本地js檔案
 * @param url
 * @param injection
 * @return
 */
private WebResourceResponse handleInjectUrl(String url,String injection){
    try{
        String assetPath = url.substring(url.indexOf(injection) + injection.length(), url.length());
        String cordovaPath = JS_PATH  + assetPath;
        InputStream fis = new FileInputStream(new File(cordovaPath));
        return new WebResourceResponse(
                "application/javascript",
                "UTF-8",
                fis
        );
    }catch (Exception e){
        if (ModuleCommImpl.getInstance().isDebug()) {
            LOG.e(TAG, "handleInjectUrl loading  file fail.", e);
        }
    }
    return new WebResourceResponse("application/javascript", "UTF-8", null);
}      

此處有個優化點,非常耗時,第三點會解釋,請繼續閱讀。

2、無網情況下如何繼續通路資料?

首先h5應用需要支援離線緩存,使用localstorage把網絡資料暫存起來。Android端需要把緩存開關打開。如圖:

基于cordova實作的webview實作與h5的互動
// Enable database
// We keep this disabled because we use or shim to get around DOM_EXCEPTION_ERROR_16
String databasePath = webView.getContext().getApplicationContext().getDir("database", Context.MODE_PRIVATE).getPath();
settings.setDatabaseEnabled(true);
settings.setDatabasePath(databasePath);
// Enable AppCache
// Fix for CB-2282
settings.setCacheMode(WebSettings.LOAD_DEFAULT);   // 預設使用緩存
settings.setAppCacheMaxSize(20 * 1048576);
settings.setAppCachePath(databasePath);
// 可以讀取檔案緩存(manifest生效)
settings.setAllowFileAccess(true);
settings.setAppCacheEnabled(true);      

網上資料很多,查下即可。

3、加載首頁資料緩慢?

h5應用往往遇到加載慢,體驗不好的問題。在我們做了離線緩存時,稍微好點。但是此項目中遇到一個問題就是加載資料慢。

排查思路:

a、檢查首頁webview對象初始化時間

期初懷疑是對象初始化耗時,經列印時間,發現不是。

b、檢查onPageStarted  和onPageFinished時間。

如果此處耗時比較大,就存在問題,當初我們這邊耗時800ms,後來發現攔截代碼,擷取路徑函數

基于cordova實作的webview實作與h5的互動
public static File getCacheDirectory(Context context, boolean preferExternal, boolean persist) {
   File appCacheDir = null;
   String externalStorageState;
   try {
      externalStorageState = Environment.getExternalStorageState();
   } catch (NullPointerException e) { // (sh)it happens (Issue #660)
      externalStorageState = "";
   }      

該方法調用時間10ms,單次調用沒什麼問題。

對于我們加載本地js,比如本地60個js,針對浏覽器,并行加載6個js,也就是加載所有的js需要總的時間:600ms,太費時了。

是以我們把路徑寫出

private static final String JS_PATH = ModuleCommImpl.getInstance().getFileJsPath()+"/plugin.apis/";      

時間立馬下降了。

此處一個優化點。後續開發者在做攔截時,需要考慮下。

c、頁面沒有渲染好的問題,需要h5優化。這裡就不描述了。

繼續閱讀