查看具有Web视图快速滚动的分页器

时间:2014-09-04 13:47:28

标签: android webview android-viewpager

我需要在每个页面上使用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失败;清除背景颜色。

这个问题有什么简单的解决方法吗?我不应该使用任何外部代码,库或类似的东西 - 我应该自己编写所有代码。

1 个答案:

答案 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 
}