我需要在每个页面上使用webview制作视图寻呼机。应用程序将从服务器下载远程(大)图像到设备缓存,当下载完成时,它应该出现在当前的webview中。这是我的查看寻呼机项目布局:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#000000"
android:gravity="center"
android:padding="10dp" >
<WebView
android:id="@+id/image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#00000000"
android:padding="1dp" />
</RelativeLayout>
这是我在视图寻呼机适配器中的instantiateItem方法:
public Object instantiateItem(ViewGroup container, int position) {
inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View itemView = inflater.inflate(R.layout.viewpager_item, container,
false);
imgflag = (WebView) itemView.findViewById(R.id.image);
imgflag.setBackgroundColor(0x000000);
imgflag.getSettings().setBuiltInZoomControls(true);
imgflag.getSettings().setUseWideViewPort(true);
imgflag.getSettings().setLoadWithOverviewMode(true);
DownloadImageTask task = new DownloadImageTask(urls[position]);
task.execute();
((ViewPager) container).addView(itemView);
return itemView;
}
这是DownloadImageTask类:
private class DownloadImageTask extends AsyncTask<String, Void, Bitmap> {
String imageUrl;
String filename;
public DownloadImageTask(String url)
{
super();
this.imageUrl=url;
}
protected Bitmap doInBackground(String... urls) {
Bitmap image = null;
Log.d("Start", "Start downloading");
filename=imageUrl.replace('/', '-');
filename=filename.replace('.', '-');
filename=filename.replace(':', '-');
File file=new File(context.getCacheDir(), filename);
if(file.exists())
{
BitmapFactory.Options options = new BitmapFactory.Options();
options.inPreferredConfig = Bitmap.Config.ARGB_8888;
Bitmap bitmap = BitmapFactory.decodeFile(context.getCacheDir() + "/" + filename);
return bitmap;
}
URL url;
try {
url = new URL(imageUrl);
HttpURLConnection ucon = (HttpURLConnection) url.openConnection();
image = BitmapFactory.decodeStream(ucon.getInputStream());
File cacheDir = context.getCacheDir();
File imageFile = new File(cacheDir, filename);
FileOutputStream fos;
fos = new FileOutputStream(imageFile);
image.compress(Bitmap.CompressFormat.JPEG, 100, fos);
fos.close();
fos.flush();
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return image;
}
protected void onPostExecute(Bitmap result) {
if(result!=null)
{
String style="width='100%'";
if(result.getWidth()>result.getHeight())
style="height='100%'";
String base = context.getCacheDir().getAbsolutePath().toString();
String imagePath = "file://"+ base + "/" + filename;
String html = "<html><head></head><body><img " + style + " src=\""+ imagePath + "\"></body></html>";
imgflag.loadDataWithBaseURL("", html, "text/html","utf-8", "");
}
}
}
当我逐页慢慢滚动时,一切都很完美......但如果我快速滚动大约10-20页(无需等待每一个加载),它就无法正常工作。它不会崩溃或类似的东西,但视图只是黑色。当我离开开始加载的页面时,开始下载不会停止,它仍会在后台加载图像,所以它可能会导致问题?当它没有加载图像时,控制台说:nativeOnDraw失败;清除背景颜色。
这个问题有什么简单的解决方法吗?我不应该使用任何外部代码,库或类似的东西 - 我应该自己编写所有代码。
答案 0 :(得分:0)
问题的根本原因是您要快速连续启动大量AsyncTasks。它们在自己的线程中运行。如果您滚动浏览20页,则表示您同时尝试从远程源下载最多20张图像。可以通过调用其AsyncTask.cancel(true)
方法来取消AsyncTask,但这不是很有用,因为您还必须在AsyncTask.isCancelled()
方法中检查doInBackground()
。由于你只是在执行一项长期任务,所以这并不是很有帮助。此外,您的ViewPager负责维护您的WebView,因此确定何时调用它将很困难。
我建议在实例化ViewPager适配器后立即尝试下载所有图像。如果图像尚未下载,您还需要显示占位符图像。
所以你的AsyncTask看起来像这样:
private class DownloadImages extends AsyncTask<String, Void, Void> {
private List<String> mUrls
public DownloadImagesTask(List<String> urls){
mUrls = urls;
}
protected Void doInBackground(){
for(String url : mUrls){
if(isCancelled())
break;
//Your code to download and save the files locally
}
你的ViewPager适配器就是这样的
public Object instantiateItem(ViewGroup container, int position) {
inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View itemView = inflater.inflate(R.layout.viewpager_item, container,
false);
imgflag = (WebView) itemView.findViewById(R.id.image);
imgflag.setBackgroundColor(0x000000);
imgflag.getSettings().setBuiltInZoomControls(true);
imgflag.getSettings().setUseWideViewPort(true);
imgflag.getSettings().setLoadWithOverviewMode(true);
String imageUrl = urls[position]
//Your code to turn url into filepath
//If file exists - display set WebView image = file
//Otherwise set WebView image to placeholder file
}