在做混合應用的時候,有幾個痛點,一個是無網(wǎng)絡無法使用,還有一個是受網(wǎng)絡環(huán)境影響的網(wǎng)頁加載速度。今天就這兩個問題,和大家交流一下自己的經(jīng)驗。
離線緩存
這個比較容易,開啟webView的緩存功能就可以了。
WebSettings settings = webView.getSettings();
settings.setAppCacheEnabled(true);
settings.setDatabaseEnabled(true);
settings.setDomStorageEnabled(true);//開啟DOM緩存,關閉的話H5自身的一些操作是無效的
settings.setCacheMode(WebSettings.LOAD_DEFAULT);
這邊我們通過setCacheMode方法來設置WebView的緩存策略,WebSettings.LOAD_DEFAULT是默認的緩存策略,它在緩存可獲取并且沒有過期的情況下加載緩存,否則通過網(wǎng)絡獲取資源。這樣的話可以減少頁面的網(wǎng)絡請求次數(shù),那我們?nèi)绾卧陔x線的情況下也能打開頁面呢,這里我們在加載頁面的時候可以通過判斷網(wǎng)絡狀態(tài),在無網(wǎng)絡的情況下更改webview的緩存策略。
ConnectivityManager cm = (ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo info = cm.getActiveNetworkInfo();
if(info.isAvailable())
{
settings.setCacheMode(WebSettings.LOAD_DEFAULT);
}else
{
settings.setCacheMode(WebSettings.LOAD_CACHE_ONLY);//不使用網(wǎng)絡,只加載緩存
}
這樣我們就可以使我們的混合應用在沒有網(wǎng)絡的情況下也能使用一部分的功能,不至于什么都顯示不了了,當然如果我們將緩存做的更好一些,在網(wǎng)絡好的時候,比如說在WIFI狀態(tài)下,去后臺加載一些網(wǎng)頁緩存起來,這樣處理的話,即使在無網(wǎng)絡情況下第一次打開某些頁面的時候,也能將該頁面顯示出來。
當然緩存資源后隨之會帶來一個問題,那就是資源無法及時更新,WebSettings.LOAD_DEFAULT中的頁面中的緩存版本好像不是很起作用,所以我們這邊可能需要自己做一個緩存版本控制。這個緩存版本控制可以放在APP版本更新中。
if (upgrade.cacheControl > cacheControl)
{
webView.clearCache(true);//刪除DOM緩存
VersionUtils.clearCache(mContext.getCacheDir());//刪除APP緩存
try
{
mContext.deleteDatabase("webview.db");//刪除數(shù)據(jù)庫緩存
mContext.deleteDatabase("webviewCache.db");
}
catch (Exception e)
{
}
}
預加載
有時候一個頁面資源比較多,圖片,CSS,js比較多,還引用了JQuery這種龐然巨獸,從加載到頁面渲染完成需要比較長的時間,有一個解決方案是將這些資源打包進APK里面,然后當頁面加載這些資源的時候讓它從本地獲取,這樣可以提升加載速度也能減少服務器壓力。重寫WebClient類中的shouldInterceptRequest方法,再將這個類設置給WebView。
webView.setWebViewClient(new WebViewClient()
{
@Override
public WebResourceResponse shouldInterceptRequest(WebView view, String url)
{
if (url.contains("[tag]"))
{
String localPath = url.replaceFirst("^http.*[tag]\\]", "");
try
{
InputStream is = getApplicationContext().getAssets().open(localPath);
Log.d(TAG, "shouldInterceptRequest: localPath " + localPath);
String mimeType = "text/javascript";
if (localPath.endsWith("css"))
{
mimeType = "text/css";
}
return new WebResourceResponse(mimeType, "UTF-8", is);
}
catch (Exception e)
{
e.printStackTrace();
return null;
}
}
else
{
return null;
}
}
});
這里我們隊頁面中帶有特殊標記的請求進行過濾替換,也就是上面代碼中的[tag],這個可以跟做后臺開發(fā)的同事約定好來就行了。對圖片資源或者其他資源進行替換也是可以的。補充一個小點可以通過settings.setLoadsImagesAutomatically(true);來設置在頁面裝載完成之后再去加載圖片。
H5優(yōu)化
Android的OnPageFinished事件會在Javascript腳本執(zhí)行完成之后才會觸發(fā)。如果在頁面中使 用JQuery,會在處理完DOM對象,執(zhí)行完$(document).ready(function() {});事件自會后才會渲染并顯示頁面。而同樣的頁面在iPhone上卻是載入相當?shù)目?,因為iPhone是顯示完頁面才會觸發(fā)腳本的執(zhí)行。所以我們這邊的解決方案延遲JS腳本的載入,這個方面的問題是需要Web前端工程師幫忙優(yōu)化的,網(wǎng)上應該有比較多LazyLoad插件,這里放一個比較老的鏈接Painless JavaScript lazy loading with LazyLoad,同樣也放上一小段前端代碼,僅供參考。
<script src="/css/j/lazyload-min.js" type="text/javascript"></script>
<script type="text/javascript" charset="utf-8">
loadComplete() {
//instead of document.read();
}
function loadscript() {
LazyLoad.loadOnce([
'/css/j/jquery-1.6.2.min.js',
'/css/j/flow/jquery.flow.1.1.min.js',
'/css/j/min.js?v=2011100852'
], loadComplete);
}
setTimeout(loadscript,10);
</script>