浅谈Android开发Webview的Loading使用效果

 更新时间:2023年02月02日 11:30:25   作者:流浪汉kylin  
这篇文章主要为大家介绍了浅谈Android开发Webview的Loading使用效果详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

前言

在开发webview的loading效果的时候会有一些问题,这边记录一些碰到的常见的问题,并且设计出一套Loading的方案来解决相关的问题。

1. loading的选择

开发loading效果的原因在于webview加载页面的时候,有时候会耗时,导致不显示内容又没有任何提示,效果不太好,所以需要在webview使用的地方加上loading的效果,其实更好的体验是还要加上EmptyView,我这边主要就以loadingView来举例。

那开发这loading基本有两种方式,一种是使用window,也就是Dialog这些弹窗的方式,在加载时弹出弹窗,在加载结束后关闭弹窗,有些人可能会封装好一些loading弹窗,然后在这里复用。

这个方法的好处是如果你封装好了,能直接复用,省去很多代码。缺点也很明显,弹窗弹出的时候是否处于一个不允许交互的情况,如果这个流程有问题,那便一直无法和页面做交互

另一种方法是直接在webview的上层覆盖一个LoadingView,webview是继承FrameLayout,就是也可以直接addView。

这个方法的好处就是不会出现上面的问题,因为我webview所在的页面关闭了,它的loading也会跟着一起消失,而且显示的效果会好一些。缺点就是可能一些特殊的webview你会单独做操作,导致会多写一些代码

没有说哪种方法是实现会比较好,主要看使用的场景和具体的需求。

2. loading显示时机的问题

我们做loading的思路就是加载开始的时候显示,加载完成之后关闭,那选择这个开始的时机和结束的时机就比较重要了。

大多数人都会直接使用WebViewClient的onPageStarted回调作为开始时机,把onPageFinished的回调,觉得直接这样写就行了,无所谓,反正webview会出手。

这个思路确实能在正常的情况下显示正常,但是在弱网情况下呢?复杂的网络环境下呢?有些人可能也会碰到一些这样的情况,loading的show写在onPageStarted中,加载时会先白屏一下,才开始显示loading,但是这个白屏的时间很短,所以觉得无所谓。但有没有想过这在正常网络环境下的白屏一下放到复杂的有问题的网络环境中会被放大成什么样。

这个加载过程其实大体分为两个阶段,从loadurl到WebViewClient的onPageStarted和从WebViewClient的从onPageStarted到onPageFinished

所以我的做法是在loadurl的时候去start loading,而不是WebViewClient的onPageStarted回调的时候。

这个是开始的时机,那结束的时机会不会有问题,还真可能有,有时候你会发现一种现象,加载完之后,你的H5内容和loading会同时显示一段时间,才关闭loading(几年前有碰到过,写这篇文章的时候测试没有复现过,不知道是不是版本更新修复了这个问题)

那如果碰到这个问题该怎么解决呢?

碰到这个问题,说明onPageFinished的回调时机在页面加载完之后,所以不可信。我们知道除了这个方法之外,BaseWebChromeClient也有个方法onProgressChanged表示加载的进度,当然这个进度你拿去判断也会有问题,因为它并不会每次都会回调100给你,可能有时候给你96,就没了。我以前的做法是双重判断,判断是进度先返回>85还是onPageFinished先调用,只要有一个调用,我都会关闭loading

3. 体验优化

当然处理好显示的关闭的时机还不行,想想如果在loadurl中show loading会怎样,没错,就算网速快的情况,页面让loading一闪而过,那这样所造成的体验就很不好,所以我们需要做一个延迟显示,我个人习惯是延迟0.5秒。当然延迟显示也会有延迟显示的问题,比如延迟到0.3秒的时候你关闭页面怎么办,再0.2秒之后我总不不能让它显示吧。

说了显示,再说关闭。无论是onPageFinished方法还是onProgressChanged,你能保证它一定会有回调吗?这些代码都不是可控的,里面会不会出现既没抛异常,也没给回调的情况。也许有人说不会的,我都用了这么多年了,没出现过这种问题,但是既然不是我们可控的代码,加一层保险总没错吧。

其实这也简单,定一个timeout的逻辑就行,我个人是定义10秒超时时间,如果10秒后没有关闭loading,我就手动关闭并显示emptyview的error页面。这个超时时间还是比较实用,最上面说了loading的选择,如果你的loading做成view,那即便没有这个逻辑也影响不大,最多就会菊花一直转,但如果你是window做的,没有超时的处理,又没有回调,那你的window会一直显示卡住页面。

4. loading最终设计效果

基于上面的情况,我写个Demo,首先loading的选择,我选择基于view,所以要写个自定义View

public class WebLoadingView extends RelativeLayout {
    private Context mContext;
    // 0:正常状态;1:loading状态;2:显示loadingview状态
    private AtomicInteger state;  
    private Handler lazyHandler;
    private Handler timeOutHandler;
    public BaseWebLoadingView(Context context) {
        super(context);
        init(context);
    }
    public BaseWebLoadingView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context);
    }
    public BaseWebLoadingView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context);
    }
    private void init(Context context) {
        this.mContext = context;
        state = new AtomicInteger(0);
        lazyHandler = new Handler(Looper.getMainLooper());
        timeOutHandler = new Handler(Looper.getMainLooper());
        initView();
    }
    private void initView() {
        LayoutInflater.from(mContext).inflate(R.layout.demo_loading, this, true);
    }
    public void show() {
        if (state.compareAndSet(0, 1)) {
            lazyHandler.postDelayed(new Runnable() {
                @Override
                public void run() {
                    if (state.compareAndSet(1, 2)) {
                        setVisibility(View.VISIBLE);
                    }
                }
            }, 500);
            timeOutHandler.postDelayed(new Runnable() {
                @Override
                public void run() {
                    close();
                }
            }, 10000);
        }
    }
    public void close() {
        state.set(0);
        setVisibility(View.GONE);
        try {
            lazyHandler.removeCallbacksAndMessages(null);
            timeOutHandler.removeCallbacksAndMessages(null);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

代码应该都比较好理解,就不过多介绍了,然后在自定义webview的loadurl里面展示

@Override
public void loadUrl(String url) {
    if (webLoadingView != null && !TextUtils.isEmpty(url) && url.startsWith("http")) {
        webLoadingView.show();
    }
    super.loadUrl(url);
}

写这里主要是有个地方要注意,就是调方法时也会执行这个loadUrl,所以要判断是加载网页的时候才显示loading。

总结

总结几个重点吧,第一个是对第三方的东西(webview这个也类似第三方吧,坑真的很多),我们没办法把控它的流程,或者说没办法把控它的生命周期,所以要封装一套流程逻辑去给调用端方便去使用。
第二个问题是版本的问题,也许会出现不同的版本所体现的效果不同,这个是需要留意的。

如果要完美解决这堆loading相关的问题,最好的方法就是看源码,你知道它里面是怎么实现的,为什么会出现onPageStarted之前还会有一段间隔时间,那就去看loadUrl和onPageStarted回调之间的源码,看它做了什么操作嘛。我个人是没看源码,所以这里只能说是浅谈。

以上就是浅谈Android开发Webview的Loading使用效果的详细内容,更多关于Android Webview Loading的资料请关注脚本之家其它相关文章!

相关文章

  • Android EditText实现输入金额类型详解

    Android EditText实现输入金额类型详解

    EditText是Android中一个非常实用的控件,有很多InputType,可以来达到不同的输入效果,下面这篇文章主要给大家介绍了关于Android EditText实现输入金额类型的相关资料,需要的朋友可以参考借鉴,下面来一起看看吧。
    2017-09-09
  • Android如何获取APP启动时间

    Android如何获取APP启动时间

    大家好,本篇文章主要讲的是Android如何获取APP启动时间,感兴趣的同学赶快来看一看吧,对你有帮助的话记得收藏一下,方便下次浏览
    2021-12-12
  • Android录音并且输出为Mp4文件的方法教程

    Android录音并且输出为Mp4文件的方法教程

    这篇文章主要给大家介绍了关于Android录音并且输出为Mp4文件的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2018-08-08
  • Android中如何安全地打印日志详解

    Android中如何安全地打印日志详解

    日志是我们在日常开发中必不可少的一部分,下面这篇文章主要给大家介绍了关于Android中如何安全地打印日志的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们一起来看看吧。
    2017-12-12
  • Android开发之利用jsoup解析HTML页面的方法

    Android开发之利用jsoup解析HTML页面的方法

    这篇文章主要介绍了Android开发之利用jsoup解析HTML页面的方法,结合实例形式分析了Android基于jsoup jar包来抓取html页面的实现技巧,需要的朋友可以参考下
    2016-03-03
  • Kotlin新手基础学习之Elvis操作符

    Kotlin新手基础学习之Elvis操作符

    Kotlin 是一种在 Java 虚拟机上运行的静态类型编程语言,被称之为 Android 世界的Swift,由 JetBrains 设计开发并开源,下面这篇文章主要给大家介绍了关于Kotlin新手基础学习之Elvis操作符的相关资料,需要的朋友可以参考下。
    2017-12-12
  • android开发实现文件读写

    android开发实现文件读写

    这篇文章主要为大家详细介绍了android开发实现文件读写,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-07-07
  • Android自定义格式显示Button的布局思路

    Android自定义格式显示Button的布局思路

    下文的效果都是xml布局文件实现的,一张图片都未曾使用,顺便贴出几个布局文件留个大家参考下,感性的朋友可不要错过了哈
    2013-04-04
  • flutter实现倒计时加载页面

    flutter实现倒计时加载页面

    这篇文章主要为大家详细介绍了flutter实现倒计时加载页面,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-03-03
  • TabLayout+ViewPager2的简单使用详解

    TabLayout+ViewPager2的简单使用详解

    这篇文章主要为大家详细介绍了TabLayout+ViewPager2的简单使用,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-09-09

最新评论