Android 如何从AsyncTask更新webview
我有一个应用程序,它从网络上获取一个xml文件,解析它以检索到我必须缓存的站点网页的路径Android 如何从AsyncTask更新webview,android,webview,android-asynctask,Android,Webview,Android Asynctask,我有一个应用程序,它从网络上获取一个xml文件,解析它以检索到我必须缓存的站点网页的路径 /services/orthopaedics.php 。 我可以成功下载所有需要缓存的页面的路径。目前,我在一个异步任务中执行此操作。网页的webservice调用路径的结果存储在AsyncTask的doInBackground方法中的ContentsValue中。然后我在onPostExecute方法中遍历这些ContentsValue,我可以在webview的loadUrl方法中逐个加载网页。此web
/services/orthopaedics.php
。
我可以成功下载所有需要缓存的页面的路径。目前,我在一个异步任务中执行此操作。网页的webservice调用路径的结果存储在AsyncTask的doInBackground方法中的ContentsValue中。然后我在onPostExecute方法中遍历这些ContentsValue,我可以在webview的loadUrl方法中逐个加载网页。此webview不可见,因为它仅用于缓存目的
问题是,由于不可见的webview正在加载另一个用户可以看到的webview,并且要显示站点的索引页,因此加载速度变慢。在不可见的webview停止加载缓存之前,将出现一个白色屏幕。在phoe上大约需要4秒,这是可以接受的,但在android平板电脑上大约需要30秒
我知道对webview的调用必须在UI线程上,这就是我在onPostExecute方法中加载WebPagesInvisibleWebView的原因。是否有可能以某种方式将页面加载到doInBacground方法中的缓存中,但将webview.loadUrl放在runOnUiThreadnew Runnable中
下面我将给出一个简单的例子来说明我的意思
private class AsyncCacheSite extends AsyncTask<String, ContentValues, ContentValues>{
ProgressDialog progressDialog;
@Override
protected void onPreExecute() {
super.onPreExecute();
Log.e(TAG, "about to load main page");
webView.loadUrl(mobileWebsiteUrl, getHeaders());
progressDialog = new ProgressDialog(MainActivity.this);
progressDialog.setTitle("Connecting to Server");
progressDialog.setMessage("Caching website for offline use...");
progressDialog.setIndeterminate(true);
progressDialog.show();
}
@Override
protected ContentValues doInBackground(String... params) {
ContentValues cv = null;
try {
//call the service to get the xml file containing paths
cv = ws.checkForUpdates();
} catch (Exception e) {
e.printStackTrace();
}
//iterate through the xml file geting the paths
.......
.......
.......
runOnUiThread(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
loadUrlIntoCache(page);
}
})
return null;
}
@Override
protected void onPostExecute(ContentValues result) {
super.onPostExecute(result);
progressDialog.dismiss();
}//end of postExecute
}//end of asyncTask
public void loadUrlIntoCache(String pageUrl){
WebView wv2 = new WebView(MainActivity.this);
wv2.getSettings().setSupportZoom(true);
wv2.getSettings().setBuiltInZoomControls(true);
wv2.setScrollBarStyle(WebView.SCROLLBARS_OUTSIDE_OVERLAY);
wv2.setScrollbarFadingEnabled(true);
wv2.getSettings().setLoadsImagesAutomatically(true);
wv2.getSettings().setDomStorageEnabled(true);
wv2.getSettings().setAppCacheEnabled(true);
// Set cache size to 8 mb by default. should be more than enough
wv2.getSettings().setAppCacheMaxSize(1024*1024*32);
// This next one is crazy. It's the DEFAULT location for your app's cache
// But it didn't work for me without this line.
// UPDATE: no hardcoded path. Thanks to Kevin Hawkins
String appCachePath = getApplicationContext().getCacheDir().getAbsolutePath();
wv2.getSettings().setAppCachePath(appCachePath);
wv2.getSettings().setAllowFileAccess(true);
wv2.getSettings().setJavaScriptEnabled(true);
// wv2.setWebViewClient(new WebViewClient());
////////////////////////////////////////////////////////////////////////////////////////
/////the webviewclient below is the code you gave me to overcome the redirecting issue//
////////////////////////////////////////////////////////////////////////////////////////
webView.setWebViewClient(new WebViewClient() {
public boolean shouldOverrideUrlLoading(WebView view, String url){
// do your handling codes here, which url is the requested url
// probably you need to open that url rather than redirect:
view.loadUrl(url);
return false; // then it is not handled by default action
}
});
wv2.getSettings().setCacheMode(WebSettings.LOAD_DEFAULT);
wv2.setVisibility(View.GONE);
wv2.loadUrl(mobileWebsiteUrl + pageUrl, getHeaders());
Log.e(TAG, "loading " + mobileWebsiteUrl + pageUrl);
}
我认为唯一的解决方案是在doInBackground中使用http请求加载数据,然后使用
在publishProgress中。我认为唯一的解决方案是在doInBackground中使用http请求加载数据,然后使用
正在发布中。很遗憾,您无法从异步任务加载URL。必须从主线程调用所有WebView方法
您所能做的就是在第二个线程中更新进度对话框。请检查此答案。很遗憾,您无法从异步任务加载URL。必须从主线程调用所有WebView方法
您所能做的就是在第二个线程中更新进度对话框。检查此答案。需要从UI线程调用WebView。如果您有权访问主循环器,则可以通过UI线程处理程序创建、设置和加载页面
//Code for creating an instance of Webview inside AsyncTask
WebView wv = null;
final Object lock = new Object();
final int TIMEOUT_MS = 3000;
AtomicReference<WebView> holder = new AtomicReference<>(); //use to pass the created webview back to worker thread.
Handler mainHandler = new Handler(Looper.getMainLooper());
try {
synchronized (lock) {
while (wv == null) {
mainHandler.post(() -> {
synchronized (lock) {
WebView localWebView = new WebView(context);
setWebViewCache(context, localWebView); //configure the cache to your desired location.
holder.set(localWebView); //use this line to pass out the created instance from the UI thread back to your async task.
lock.notify();
}
});
lock.wait(TIMEOUT_MS);
wv = holder.get();
}
}
} catch (InterruptedException ie) {
Log.e(TAG, "creating prefetch webview times out");
}
希望我的代码能有所帮助。需要从UI线程调用WebView。如果您有权访问主循环器,则可以通过UI线程处理程序创建、设置和加载页面
//Code for creating an instance of Webview inside AsyncTask
WebView wv = null;
final Object lock = new Object();
final int TIMEOUT_MS = 3000;
AtomicReference<WebView> holder = new AtomicReference<>(); //use to pass the created webview back to worker thread.
Handler mainHandler = new Handler(Looper.getMainLooper());
try {
synchronized (lock) {
while (wv == null) {
mainHandler.post(() -> {
synchronized (lock) {
WebView localWebView = new WebView(context);
setWebViewCache(context, localWebView); //configure the cache to your desired location.
holder.set(localWebView); //use this line to pass out the created instance from the UI thread back to your async task.
lock.notify();
}
});
lock.wait(TIMEOUT_MS);
wv = holder.get();
}
}
} catch (InterruptedException ie) {
Log.e(TAG, "creating prefetch webview times out");
}
希望我的代码能帮上忙。你能告诉我怎么做吗