WebView的緩存可以分為頁面緩存和數據緩存。
頁面緩存是指加載一個網頁時的html、JS、CSS等頁面或者資源數據。這些緩存資源是由于瀏覽器的行為而產生,開發者只能通過配置HTTP響應頭影響瀏覽器的行為才能間接地影響到這些緩存數據。
他們的索引存放在/data/data/package_name/databases下。他們的文件存放在/data/data/package_name/cache/xxxwebviewcachexxx下。文件夾的名字在2.x和4.x上有所不同,但都文件夾名字中都包含webviewcache。
數據緩存分為兩種:AppCache和DOM Storage(Web Storage)。他們是因為頁面開發者的直接行為而產生。所有的緩存數據都由開發者直接完全地掌控。
AppCache使我們能夠有選擇的緩沖web瀏覽器中所有的東西,從頁面、圖片到腳本、css等等。尤其在涉及到應用于網站的多個頁面上的CSS和JavaScript文件的時候非常有用。其大小目前通常是5M。
在Android上需要手動開啟(setAppCacheEnabled),并設置路徑(setAppCachePath)和容量(setAppCacheMaxSize)
Android中Webkit使用一個db文件來保存AppCache數據(my_path/ApplicationCache.db)
如果需要存儲一些簡單的用key/value對即可解決的數據,DOM Storage是非常完美的方案。根據作用范圍的不同,有Session Storage和Local Storage兩種,分別用于會話級別的存儲(頁面關閉即消失)和本地化存儲(除非主動刪除,否則數據永遠不會過期)。
在Android中可以手動開啟DOM Storage(setDomStorageEnabled),設置存儲路徑(setDatabasePath)
Android中Webkit會為DOM Storage產生兩個文件(my_path/localstorage/http_h5.m.taobao.com_0.localstorage和my_path/localstorage/Databases.db)
另外,在Android中清除緩存時,如果需要清除Local Storage的話,僅僅刪除Local Storage的本地存儲文件是不夠的,內存里面有緩存數據。如果再次進入頁面,Local Storage中的緩存數據同樣存在。需要殺死程序運行的當前進程再重新啟動才可以。
HTML5的離線應用功能可以使得WebApp即使在網絡斷開的情況下仍能正常使用,這是個非常有用的功能。近來工作中也要用到HTML5離線應用功能,由于是在Android平臺上做,所以自然而然的選擇Webview來解析網頁。但如何使Webivew支持HTML5離線應用功能呢,經過反復摸索和上網查找資料,反復做試驗終于成功了。
首先需配置webview的的一些屬性,假設activity中已經有了一個Webview的實例對象,名為m_webview,然后增加以下代碼:
WebSettings webseting = m_webview.getSettings();
webseting.setDomStorageEnabled(true);
webseting.setAppCacheMaxSize(1024*1024*8);//設置緩沖大小,我設的是8M
String appCacheDir = this.getApplicationContext().getDir("cache", Context.MODE_PRIVATE).getPath();
webseting.setAppCachePath(appCacheDir);
webseting.setAllowFileAccess(true);
webseting.setAppCacheEnabled(true);
webseting.setCacheMode(WebSettings.LOAD_DEFAULT);
webview可以設置一個WebChromeClient對象,在其onReachedMaxAppCacheSize函數對擴充緩沖做出響應。代碼如下:
m_webview.setWebChromeClient(m_chromeClient);
private WebChromeClient m_chromeClient = new WebChromeClient(){
//擴充緩存的容量
@Override
public void onReachedMaxAppCacheSize(long spaceNeeded,
long totalUsedQuota, WebStorage.QuotaUpdater quotaUpdater) {
quotaUpdater.updateQuota(spaceNeeded * 2);
}
};
其次要修改http服務器中的配置,使其支持text/cache-manifest,我使用的是apache服務器,是windows版本的,在apache的conf文件夾中找到mime.types文件,打開后在文件的最后加上
“text/cache-manifest
mf manifest”,重啟服務器即可。這一步很重要,我就是因為服務器端沒有配置這個,所以失敗了好多次,最后是在附錄鏈接1的回復中找到的線索。
經過以上設置Webview就可以支持HTML5的離線應用了。
附錄鏈接1中說緩沖目錄應該是getApplicationContext().getCacheDir().getAbsolutePath();但我經過試驗后發現設置那個目錄不起作用,可能是Android版本不同吧,我的是Android4.0.3,而他的可能是以前的Android版本吧。
緩沖目錄使用
getApplicationContext().getDir("cache", Context.MODE_PRIVATE).getPath()是從附錄鏈接2中找到的線索。
附錄鏈接:
1.http://alex.tapmania.org/2010/11/html5-cache-android-webview.html
2.http://johncookie.iteye.com/blog/1182459
3.HTML5 Offline官方文檔:http://www.w3.org/TR/html5/offline.html#manifests
原因:
webview加載 服務端的網頁,為了減少訪問壓力,用html5緩存技術,本地建了數據庫,在手機瀏覽器里 可以顯示頁面,換成webView就不行了。
public class efan_NewsReader extendsActivity {
/** Called when the activity is first created. */
@Override
publicvoidonCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
WebView myWebView=(WebView)findViewById(R.id.my_webview);
myWebView.setWebViewClient(newWebViewClient());
WebSettings settings = myWebView.getSettings();
// 開啟javascript設置
settings.setJavaScriptEnabled(true);
// 設置可以使用localStorage
settings.setDomStorageEnabled(true);
// 應用可以有數據庫
settings.setDatabaseEnabled(true);
String dbPath =this.getApplicationContest().getDir("database", Context.MODE_PRIVATE).getPath();
settings.setDatabasePath(dbPath);
// 應用可以有緩存
settings.setAppCacheEnabled(true);
String appCaceDir =this.getApplicationContext().getDir("cache", Context.MODE_PRIVATE).getPath();
settings.setAppCachePath(appCaceDir);
myWebView.loadUrl("http://10.10.35.47:8080/html5test/test.htm");
}
}
HTML5 page source code:
<htmlmanifest="mymanifest.manifest">
<head>
<metahttp-equiv="Content-Type"content="text/html; content="no-cache"charset=utf-8" />
<scripttype="text/javascript"src="js/jquery-1.6.1.min.js"></script>
<script>
$(document).ready(function(){
databaseTest();
});
function databaseTest(){
//open database
var db = openDatabase('mydb', '1.0', 'Test DB', 2 * 1024 * 1024);
db.transaction(function (tx) {
tx.executeSql('CREATE TABLE IF NOT EXISTS testHtml (id unique, contentText)');
tx.executeSql('INSERT INTO testHtml (contentText) VALUES ("insert data test!")');
});
db.transaction(function(tx){
tx.executeSql('SELECT * FROM testHtml',[],function(tx,result){
var len=result.rows.length;
var msg = "<p>Found rows: " + len + "</p>";
$("#testinfo").append(msg);
},null);
});
}
</script>
</head>
<body>
<div>here is test info:</div>
<divid="testinfo"></div>
</body>
其他設置還有:
settings.setCacheMode(WebSettings.LOAD_DEFAULT); // 默認使用緩存
settings.setAppCacheMaxSize(810241024); //緩存最多可以有8M
settings.setAllowFileAccess(true); // 可以讀取文件緩存(manifest生效)
in WebChromeClient :
myWebView.setWebChromeClient(newWebChromeClient()
{
@Override
publicvoidonExceededDatabaseQuota(String url, String databaseIdentifier,
longcurrentQuota,longestimatedSize,longtotalUsedQuota,
WebStorage.QuotaUpdater quotaUpdater)
{
quotaUpdater.updateQuota(estimatedSize * 2);
}
}
myWebView.setWebChromeClient(newWebChromeClient()
{
// 擴充緩存的容量
@Override
publicvoidonReachedMaxAppCacheSize(longspaceNeeded,longtotalUsedQuota,
WebStorage.QuotaUpdater quotaUpdater)
{
quotaUpdater.updateQuota(spaceNeeded * 2);
}
}
按照范例,我成功的解決了我的問題,而且之前彈出框所出現的找不到數據(提示:underfine)也解決了,這個應該是當初數據庫沒設所引起的。
WebView中存在著兩種緩存:網頁數據緩存(存儲打開過的頁面及資源)、H5緩存(即appcache)。
一、網頁緩存
1、緩存構成
/data/data/package_name/cache/
/data/data/package_name/database/webview.db
/data/data/package_name/database/webviewCache.db
2、緩存模式
較難理解的是以下兩個模式:
LOAD_DEFAULT,根據cache-control決定是否從網絡上取數據。
LOAD_CACHE_ELSE_NETWORK,只要本地有,無論是否過期,或者no-cache,都使用緩存中的數據。
如:m.taobao.com的cache-control為no-cache,在模式LOAD_DEFAULT下,無論如何都會從網絡上取數據,如果沒有網絡,就會出現錯誤頁面;在LOAD_CACHE_ELSE_NETWORK模式下,無論是否有網絡,只要本地有緩存,都使用緩存。本地沒有緩存時才從網絡上獲取。
m.sina.com.cn的cache-control為max-age=60,在兩種模式下都使用本地緩存數據。
總結:根據以上兩種模式,建議緩存策略為,判斷是否有網絡,有的話,使用LOAD_DEFAULT,無網絡時,使用LOAD_CACHE_ELSE_NETWORK。
3、清除緩存
clearCache(boolean)。
CacheManager.clear。高版本中需要調用隱藏API。
4、控制大小
無系統API支持。
可選方式:定時統計緩存大小、按時間順序刪除緩存。
二、H5緩存
1、緩存構成
根據setAppCachePath(String appCachePath)提供的路徑,在H5使用緩存過程中生成的緩存文件。
2、緩存模式
無模式選擇,通過setAppCacheEnabled(boolean flag)設置是否打開。默認關閉,即,H5的緩存無法使用。
3、清除緩存
找到調用setAppCachePath(String appCachePath)設置緩存的路徑,把它下面的文件全部刪除就OK了。
4、控制大小
通過setAppCacheMaxSize(long appCacheMaxSize)設置緩存最大容量,默認為Max Integer。
同時,可能通過覆蓋WebChromeClient.onReachedMaxAppCacheSize(long requiredStorage, long quota, WebStorage.QuotaUpdater quotaUpdater)來設置緩存超過先前設置的最大容量時的策略。