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

目录
  • 前言
    • 1. loading的选择
    • 2. loading显示时机的问题
    • 3. 体验优化
    • 4. 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的资料请关注我们其它相关文章!

(0)

相关推荐

  • Android WebView输入框被档问题升级解析

    目录 前言 issue 5497问题 布局顶起后距离软键盘有一定距离 Activity的webview输入框被挡 总结 前言 之前写过一篇文章,有讲如何处理Android输入框被软键盘挡住的问题,无论是原生的还是webview的,这里面主要的问题是webview的问题比较难处理,没有看过的可以先看看  Android 输入框被挡问题完美解决方案 主要是issue 5497这个问题.然后可能有些朋友觉得,这篇文章没能解决他的问题,或者说按照我的代码去写又会出现新的问题.这说明没有能理解这篇文章写的

  • Android WebView实现全屏播放视频

    目录 介绍 主要代码 介绍 最近项目开发中用到了WebView播放视频的功能,总结了开发中犯过的错误,这些错误在开发是及容易遇到的,所以我这里总结了一下,希望大家看到后不要再犯类似的错误,尽可能提高开发效率: 这个Demo我这里也参考了网上写的一个比较好的一个Demo,经过总结修改,写出来的. 主要代码 以下是相应代码: MainActivity: package com.androidwebviewdemo; import android.app.Activity; import androi

  • Android WebView软键盘遮挡输入框方案详解

    目录 背景 纪实 方案 实现 总结 背景 笔者在使用 WebView 加载含有输入框的 H5 页面时,点击输入框后,输入框会被软键盘遮挡住,无法看到输入的内容,这很影响用户体验. 笔者想着这种业务场景比较常见,遂上网搜索一番,果不其然,有不少同志遇到这个问题,想来这个问题很好解决了.笔者一一尝试了同志们提供的解决方案,结果要不是没有作用,要不是效果不太满意,只好自己另辟蹊径了. 注:在笔者的业务场景中,App是全屏的,即没有顶部的系统栏,也没有底部的导航栏,所以笔者的解决方案,可能不适用于其他场

  • Android WebView控件基本使用示例

    Android WebView用于在 android 中显示网页.可以从相同的应用程序或 URL 加载网页.它用于在 android 活动中显示在线内容. Android WebView 使用 webkit 引擎来显示网页. android.webkit.WebView 是 AbsoluteLayout 类的子类. Android WebView 类的loadUrl()和loadData()方法用于加载和显示网页. Android WebView 示例 让我们看看使用 Web 视图显示 baid

  • Android WebView缓存机制优化加载慢问题

    目录 一 .前言 二 .WebView存在的性能问题 2.1 H5 页面加载速度慢 2.1.1 渲染速度慢 2.1.2 页面资源加载缓慢 2.2 耗费流量 2.3 总结 三 .解决方案 3.1 前端H5的缓存机制 3.1.1 缓存机制 3.1.2 缓存模式 3.2 资源预加载 3.2.1 预加载WebView对象 3.2.2 预加载H5资源 3.3 自身构建缓存 3.3.1 需求场景 3.3.2 实现步骤 3.3.3 具体实现 3.3.4 具体实例 一 .前言 由于H5具备 开发周期短.灵活性好

  • Android WebView如何判断是否滚动到底部

    目录 场景: 分析: 实现: 总结 场景: 我们有时候需要弹一些必读公告,但是呢可能会要去你看完之后才可以关掉,所以就需要滚动到底部才显示关闭按钮,而公告什么的往往又是基于富文本的,那么在展示在Android上时就要用到WebView,基于这个要求就有了判断 WebView 判断是否滚动到底部. 分析: 要判断是否到底部那么我们先来分析有哪几种情况,当html文档加载到WebView后会有一下两种情况. WebView里的html内容没有填充满,就是无滚动条情况.html内容的高度比WebVie

  • Android WebView基础应用详解

    目录 一.WebView的基础配置 二.WebView支持播放音乐 三.WebView支持视频播放 四.WebChromeClient 五.WebViewClient 1.重定向问题 2.实现预加载 3.增加错误页面展示限制 4.解决页面白屏问题 附GitHub源码:WebViewExplore 一.WebView的基础配置 WebSettings ws = getSettings(); ws.setBuiltInZoomControls(true);// 隐藏缩放按钮 ws.setLayout

  • Android webView加载数据时内存溢出问题及解决

    目录 Android webView加载数据时内存溢出 Android内存问题 (内存溢出 内存泄漏 内存抖动) 总结 Android webView加载数据时内存溢出 今天使用webView加载数据时   如果数据太长就会崩溃,造成内存溢出,在网上查找了一下资料之后   终于把它解决了,谨在此记录 1.不要在XML里面写webView 可以使用一个占位布局 <FrameLayout     android:id="@+id/layoutWebView"     android:

  • Android WebView预渲染介绍

    目录 前言 术语对齐 客户端可以从哪些方面优化h5页面的加载速度? 优化思路 预渲染的基本实现逻辑是怎样的? 预创建 预创建个数 预创建时机 预创建复用 预渲染 预渲染时机 预渲染有效性校验 时间有效性 状态有效性 页面显示状态通知 其它注意事项 预渲染存在哪些局限性? 总结 前言 在一个Hybrid项目中,必不可少的就是加载h5页面.h5页面的加载性能极大影响着用户体验,并会从各方面影响到我们APP的业务数据.试想,假设一个h5页面要花好几秒才能打开,那用户还会使用我们的APP吗?所以今天我们

  • 浅谈Android开发中项目的文件结构及规范化部署建议

    一.几句话 使用Gradle及其推荐的项目框架 把密码等敏感数据放入gradle.properties 不要自己写Http客户端,使用Volley或OkHttp库 使用Jackson库来解析JSON数据 避免Guava并出于Dalvik 65K methods limit不要使用过多的库 使用Fragment来绘制UI界面 Activity主要用来管理Fragment 布局文件XML也是代码,好好组织它们 在布局文件里,使用styles以避免重复的属性 使用多个style文件而不是一个巨大的st

  • 浅谈Android开发中ListView控件性能的一些优化方法

    ListView优化一直是一个老生常谈的问题,不管是面试还是平常的开发中,ListView永远不会被忽略掉,那么这篇文章我们来看看如何最大化的优化ListView的性能. 1.在adapter中的getView方法中尽量少使用逻辑 2.尽最大可能避免GC 3.滑动的时候不加载图片 4.将ListView的scrollingCache和animateCache设置为false 5.item的布局层级越少越好 6.使用ViewHolder 下面就具体来看一些 1.在adapter中的getView方

  • 浅谈Android开发系列网络篇之Retrofit

    Retrofit是一个不错的网络请求库,用官方自己的介绍就是: A type-safe REST client for Android and Java 看官网的介绍用起来很省事,不过如果不了解它是怎么实现的也不太敢用,不然出问题了就不知道怎么办了.这几天比较闲就下下来看了一下,了解一下大概实现方法,细节就不追究了.先来看一个官网的例子,详细说明去网官看 简单示例 首先定义请求接口,即程序中都需要什么请求操作 public interface GitHubService { @GET("/use

  • 浅谈Android性能优化之内存优化

    1.Android内存管理机制 1.1 Java内存分配模型 先上一张JVM将内存划分区域的图 程序计数器:存储当前线程执行目标方法执行到第几行. 栈内存:Java栈中存放的是一个个栈帧,每个栈帧对应一个被调用的方法.栈帧包括局部标量表, 操作数栈. 本地方法栈:本地方法栈主要是为执行本地方法服务的.而Java栈是为执行Java方法服务的. 方法区:该区域被线程共享.主要存储每个类的信息(类名,方法信息,字段信息等).静态变量,常量,以及编译器编译后的代码等. 堆:Java中的堆是被线程共享的,

  • 浅谈Android View绘制三大流程探索及常见问题

    View绘制的三大流程,指的是measure(测量).layout(布局).draw(绘制) measure负责确定View的测量宽/高,也就是该View需要占用屏幕的大小,确定完View需要占用的屏幕大小后,就会通过layout确定View的最终宽/高和四个顶点在手机界面上的位置,等通过measure和layout过程确定了View的宽高和要显示的位置后,就会执行draw绘制View的内容到手机屏幕上. 在详细介绍这三大流程之前,需要简单了解一下ViewRootImpl,View绘制的三大步骤

  • 浅谈Android中Service的注册方式及使用

    Service通常总是称之为"后台服务",其中"后台"一词是相对于前台而言的,具体是指其本身的运行并不依赖于用户可视的UI界面,因此,从实际业务需求上来理解,Service的适用场景应该具备以下条件: 1.并不依赖于用户可视的UI界面(当然,这一条其实也不是绝对的,如前台Service就是与Notification界面结合使用的): 2.具有较长时间的运行特性. 1.Service AndroidManifest.xml 声明 一般而言,从Service的启动方式上

  • 浅谈Android Studio3.6 更新功能

    前言 下载google CodeLab的程序时,提示要更新3.6版本才能运行程序,于是更新了一下,看看有什么新功能. 界面设计工具 这次更新了一些设计工具,比如Layout Editor 和 Resource Manager. 现在,在XML或设计工具的颜色选择器中,Android Studio会在您的应用程序中填充颜色资源,以便您快速选择和替换颜色资源值. 拆分视图并放大设计编辑器 设计编辑器(例如,布局编辑器和导航编辑器)现在提供一个拆分视图,使您可以同时查看UI的"设计"视图和&

  • 浅谈Android Studio 4.1 更新内容

    概览 Android Studio 4.1 目前已经发布,该版本共修复了2370 个 bug 以及 275 个 issue,主要包含如下新增功能: 设计 Material Design 组件库的更新 开发 Database Inspector 功能 直接在 Android Studio 中运行模拟器 Dagger 导航支持 使用 TensorFlow Lite 模型 构建与测试 Android 模拟器支持折叠屏 Apply Changes 更新 从 AAR 中导出 C/C++ 中的依赖 Nati

  • 浅谈Android中适配器的notifyDataSetChanged()为何有时不刷新

    学过Android开发的人都知道,ListView控件在开发中经常遇到,并且ListView通常结合Adapter适配器来进行数据显示和数据更新操作.姑且假设数据存储在名为dataList的成员变量中.数据操作无非是增加数据.删除数据这两种主要的操作,而当数据有所变化时,为了及时向用户提供更新后的数据,我们知道需要在数据更新后调用适配器的notifyDataSetChanged()方法,来显示更新后的数据.殊不知,该方法并非百试不爽,在此我们便来讨论下具体的原因,其实本质是关注内存的分配情况.

  • 浅谈Android截屏和指定View生成截图

    当前页面截图(截取整个屏幕) 截取当前Activity页面的截图,可以通过窗体最底层的decorView进行缓存,然后根据这个缓存对象生成一张图片.有的需要不需要状态栏,也可以指定生成图片的宽高,把状态栏去除. /** * 截取当前窗体的截图,根据[isShowStatusBar]判断是否包含当前窗体的状态栏 * 原理是获取当前窗体decorView的缓存生成图片 */ fun captureWindow(activity: Activity, isShowStatusBar: Boolean)

随机推荐