Flutter开发通用页面Loading组件示例详解

 更新时间:2022年11月28日 10:34:52   作者:Fitem  
这篇文章主要为大家介绍了Flutter开发通用页面Loading组件示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

前沿

页面通用Loading组件是一个App必不可少的基础功能,之前只开发过Android原生的页面Loading,这次就按原生的逻辑再开发一个Flutter的Widget,对其进行封装复用

我们先看下效果:

原理

状态

一个通用的页面加载Loading组件应该具备以下几种状态:

IDLE 初始化

Idle状态,此时的组件还只是初始化

LOADING 加载中

Loading状态,一般在网络请求或者耗时加载数据时调用,通用显示的是一个progress或者自定义的帧动画

LOADING_SUCCESS

LoadingSuccess加载成功,一般在网络请求成功后调用,并将需要展示的页面展示出来

LOADING_SUCCESS_BUT_EMPTY

页面加载成功但是没有数据,这种情况一般是发起列表数据请求但是没有数据,通常我们会展示一个空数据的页面来提醒用户

NETWORK_BLOCKED

网络错误,一般是由于网络异常、网络请求连接超时导致。此时我们需要展示一个网络错误的页面,并且带有重试按钮,让用户重新发起请求

ERROR

通常是接口错误,这种情况下我们会根据接口返回的错误码或者错误文本提示用户,并且也有重试按钮

/// 状态枚举
enum LoadingStatus {
  idle, // 初始化
  loading, // 加载中
  loading_suc, // 加载成功
  loading_suc_but_empty, // 加载成功但是数据为空
  network_blocked, // 网络加载错误
  error, // 加载错误
}

点击事件回调

当网络异常或者接口报错时,会显示错误页面,并且提供重试按钮,让用户点击重新请求。基于这个需求,我们还需要提供点击重试后的事件回调让业务可以处理重新请求。

 /// 定义点击事件
 typedef OnTapCallback = Function(LoadingView widget);

提示文案

提供提示文案的自定义,方便业务根据自己的需求展示特定的提示文案

代码实现

根据上面的原理来实现对应的代码

  • 构造方法
 /// 构造方法
 LoadingView({
    Key key,
    @required this.child, // 需要加载的Widget
    @required this.todoAfterError, // 错误点击重试
    @required this.todoAfterNetworkBlocked, // 网络错误点击重试
    this.networkBlockedDesc = "网络连接超时,请检查你的网络环境",
    this.errorDesc = "加载失败",
    this.loadingStatus = LoadingStatus.idle,
 }) : super(key: key);
  • 根据不同的Loading状态展示对应的Widget
  • 其中idle、success状态直接展示需要加载的Widget(这里也可以使用渐变动画进行切换过度)
 ///根据不同状态展示不同Widget
  Widget _buildBody() {
    switch (widget.loadingStatus) {
      case LoadingStatus.idle:
        return widget.child;
      case LoadingStatus.loading:
        return _buildLoadingView();
      case LoadingStatus.loading_suc:
        return widget.child;
      case LoadingStatus.loading_suc_but_empty:
        return _buildLoadingSucButEmptyView();
      case LoadingStatus.error:
        return _buildErrorView();
      case LoadingStatus.network_blocked:
        return _buildNetworkBlockedView();
    }
    return widget.child;
  }
  • buildLoadingView,这里简单用了系统的CircularProgressIndicator,也可以自己显示帧动画
  /// 加载中 View
  Widget _buildLoadingView() {
    return Container(
      width: double.maxFinite,
      height: double.maxFinite,
      child: Center(
        child: SizedBox(
          height: 22.w,
          width: 22.w,
          child: CircularProgressIndicator(
            strokeWidth: 2,
            valueColor: AlwaysStoppedAnimation<Color>(AppColors.primaryBgBlue),
          ),
        ),
      ),
    );
  }
  • 其他提示页面,这里做了一个统一的封装
/// 编译通用页面
  Container _buildGeneralTapView({
    String url = "images/icon_network_blocked.png",
    String desc,
    @required Function onTap,
  }) {
    return Container(
      color: AppColors.primaryBgWhite,
      width: double.maxFinite,
      height: double.maxFinite,
      child: Center(
        child: SizedBox(
          height: 250.h,
          child: Column(
            children: [
              Image.asset(url,
                  width: 140.w, height: 99.h),
              SizedBox(
                height: 40.h,
              ),
              Text(
                desc,
                style: AppText.gray50Text12,
                maxLines: 2,
                overflow: TextOverflow.ellipsis,
              ),
              SizedBox(
                height: 30.h,
              ),
              if (onTap != null)
                BorderRedBtnWidget(
                  content: "重新加载",
                  onClick: onTap,
                  padding: 40.w,
                ),
            ],
          ),
        ),
      ),
    );
  }
    /// 加载成功但数据为空 View
  Widget _buildLoadingSucButEmptyView() {
    return _buildGeneralTapView(
      url: "images/icon_empty.png",
      desc: "暂无数据",
      onTap: null,
    );
  }
  /// 网络加载错误页面
  Widget _buildNetworkBlockedView() {
    return _buildGeneralTapView(
        url: "images/icon_network_blocked.png",
        desc: widget.networkBlockedDesc,
        onTap: () {
          widget.todoAfterNetworkBlocked(widget);
        });
  }
  /// 加载错误页面
  Widget _buildErrorView() {
    return _buildGeneralTapView(
        url: "images/icon_error.png",
        desc: widget.errorDesc,
        onTap: () {
          widget.todoAfterError(widget);
        });
  }

使用

  Widget _buildBody() {
     var loadingView = LoadingView(
      loadingStatus: LoadingStatus.loading,
      child: _buildContent(),
      todoAfterNetworkBlocked: (LoadingView widget) {
        // 网络错误,点击重试
        widget.updateStatus(LoadingStatus.loading);
        Future.delayed(Duration(milliseconds: 1000), () {
          widget.updateStatus(LoadingStatus.error);
        });
      },
      todoAfterError: (LoadingView widget) {
        // 接口错误,点击重试
        widget.updateStatus(LoadingStatus.loading);
        Future.delayed(Duration(milliseconds: 1000), () {
          // widget.updateStatus(LoadingStatus.loading_suc);
          widget.updateStatus(LoadingStatus.loading_suc_but_empty);
        });
      },
    );
     Future.delayed(Duration(milliseconds: 1000), (){
       loadingView.updateStatus(LoadingStatus.network_blocked);
     });
     return loadingView;
  }

总结

至此已经完成了对整个Loading组件的封装,代码已上传Github

以上就是Flutter开发通用页面Loading组件示例详解的详细内容,更多关于Flutter通用页面Loading组件的资料请关注脚本之家其它相关文章!

相关文章

  • Android程序开发之防止密码输入错误 密码明文显示功能

    Android程序开发之防止密码输入错误 密码明文显示功能

    在使用App的时候,首次登录都需要用户输入密码的,有些朋友为了安全起见密码设置的比较长,导致很多次密码都输入错误,严重影响了用户体验效果,下面通过本文给大家介绍Android程序开发之防止密码输入错误 密码明文显示功能,需要的朋友参考下
    2016-02-02
  • Android开发之自定义CheckBox

    Android开发之自定义CheckBox

    本文通过实例代码演示如何在Android中如何自定义CheckBox,实现的效果很好,有需要的可以参考借鉴。
    2016-08-08
  • Android开发之ProgressBar字体随着进度条的加载而滚动

    Android开发之ProgressBar字体随着进度条的加载而滚动

    这篇文章主要介绍了Android开发之ProgressBar字体随着进度条的加载而滚动,需要的朋友可以参考下
    2017-09-09
  • Android TextView实现多文本折叠、展开效果

    Android TextView实现多文本折叠、展开效果

    这篇文章主要为大家详细介绍了Android TextView实现多文本折叠、展开效果,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-05-05
  • android中实现完全退出程序方法(退出所有activity)

    android中实现完全退出程序方法(退出所有activity)

    这篇文章主要介绍了android中实现完全退出程序方法(退出所有activity),本文方法是博主个人使用的一个方法,据说效果非常好,需要的朋友可以参考下
    2015-05-05
  • Android中的存储详解

    Android中的存储详解

    大家好,本篇文章主要讲的是Android中的存储详解,感兴趣的同学赶快来看一看吧,对你有帮助的话记得收藏一下,方便下次浏览
    2022-01-01
  • Android实现音频录音与播放

    Android实现音频录音与播放

    这篇文章主要为大家详细介绍了Android实现音频录音与播放,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-08-08
  • Android滑动冲突的解决技巧

    Android滑动冲突的解决技巧

    Android滑动冲突是Android开发中常见的问题,在一个界面中,可能存在多个View可以响应滑动事件,如果这些View滑动方向一致,则会导致滑动冲突,本文将从原理、使用与优化三个方面,详细介绍Android滑动冲突的解决方式,需要的朋友可以参考下
    2024-01-01
  • Android提高之手游转电视游戏的模拟操控

    Android提高之手游转电视游戏的模拟操控

    这篇文章主要介绍了Android手游转电视游戏的模拟操控方法,是非常具有实用价值的功能,需要的朋友可以参考下
    2014-08-08
  • Android中超大图片无法显示的问题解决

    Android中超大图片无法显示的问题解决

    最近在工作中发现一个问题,在做图片浏览的时候发现超大图图片无法显示,无奈只能上网找解决方法,后来通过测试找到了解决的方法,下面这篇文章就主要介绍了Android中超大图无法显示的问题解决方法,需要的朋友可以参考借鉴。
    2017-01-01

最新评论