android标题栏添加按钮_优雅地管理 loading 页面和标题栏

本文由 DylanCai 授权投稿
原文链接:https://juejin.im/post/5e5898346fb9a07cd248d179

前言

现在绝大多数 App 都需要请求网络数据,loading 动画必不可少,而网络请求会存在失败的情况,所以通常有 loading 页面也会有加载失败或者别的页面。

这些页面的样式大多时候是统一的,一般会想到的处理方式是把这些界面 include 到一个布局里,然后通过显示隐藏的方式来切换所需的视图。这样会写很多重复代码,可能会把这部分切换的逻辑抽取到 Activity 基类中或者抽取到一个自定义 View 里管理。

不过这些封装都不能解决本身存在的问题。不方便修改样式,样式有变动就需要修改已经封装好的代码。总要在布局上增加 include 代码或添加一个处理切换界面的自定义 View,多多少少有些冗余。

后面有大佬写了工具把这些处理好了,比如目前都有上千个 star 的库 LoadSir 和 Gloading 。这两个库都是很不错的,使用起来都很灵活易用。不过也有点小小的不足,因为布局上通常会有标题,我们就只能每次都对标题栏下方的子 View 进行 loading。由于标题栏样式大多时候是统一的,通常会在布局 include 一个标题栏,然后把标题栏的初始化封装在 Activity 基类中……有没发现和前面说的很像?这么写会存在着与前面相同的问题。

既然标题栏会影响到 loading 的区域,而且标题栏的通常写法所存在的问题也和 loading 界面的相似,那么如果一个 loading 库把标题栏一起管理了,会怎么样呢?

解决方案

LoadingHelper 是基于 Adapter 思想 和 ActionBar 原理实现的一个深度解耦 loading 界面和标题栏的工具,只用了一个 Kotlin 文件实现,不算上注释只有 200 多行代码。

基础用法

build.gradle 添加依赖:

dependencies {
    implementation 'com.dylanc:loadinghelper:2.0.0'
}

第一步,创建一个适配器继承  LoadingHelper.Adapter,写法与 RecyclerView.Adapter 类似。如果需要实现点击重新请求数据,可以在点击事件调用 holder.getOnReloadListener.onReload() 方法。

public 

第二步,注册适配器,传一个视图类型。有五个默认类型,也可以传任意类型数据进行注册。

new LoadingHelper(

如果想注册成全局的适配器,需要配置默认的适配器池。

LoadingHelper.setDefaultAdapterPool(adapterPool -> {
  adapterPool.register(ViewType.LOADING, new LoadingAdapter());
  return Unit.INSTANCE;
});

第三步,显示对应类型的视图。

loadingHelper.showView(viewType);
loadingHelper.showLoadingView(); // 对应视图类型 ViewType.LOADING
loadingHelper.showContentView(); // 对应视图类型 ViewType.CONTENT
loadingHelper.showErrorView(); // 对应视图类型 ViewType.ERROR
loadingHelper.showEmptyView(); // 对应视图类型 ViewType.EMPTY

动态更新已显示视图

在显示了视图之后,可以对视图进行更改刷新。用法和 RecyclerView.Adapter 一样,调用 notifyDataSetChanged() 后,会执行适配器的 onBindViewHolder() 方法。

ErrorAdapter errorAdapter = loadingHelper.getAdapter(ViewType.ERROR);
errorAdapter.errorText = "服务器繁忙,请稍后重试";
errorAdapter.notifyDataSetChanged();

高级用法

管理标题栏

如果是普通的标题栏,就是简单地在内容的上方添加标题栏:

和前面的用法类似,同样创建一个继承  LoadingHelper.Adapter 的适配器,然后就能在内容的上方添加标题栏了,可以添加多个头部。

new LoadingHelper(

如果是特殊的标题栏,比如有联动效果,就不能直接使用上面的方式了。

先实现一个不含内容的布局。

<?xml  version="1.0" encoding="utf-8"?>

创建一个类继承另一个适配器 LoadingHelper.DecorAdapter ,加载实现的布局,并指定一个 loading 的容器。

public 

最后设置一下就可以了。

new LoadingHelper(

上述的两种使用方式都是可以进行多次设置,不过每次设置会把上一次设置的样式给替换掉。

对内容进行解耦

虽然本库主要是用来管理加载界面,但最终目的是为了显示加载好的内容,内容其实也是个视图,那么应该也可以通过 Adapter 进行注册管理。不过配置管理加载界面主要是因为样式通常是统一的,而内容界面基本不一样,会有什么使用场景吗?当然是有的,我们多多少少封装过一些 Activity 基类吧,因为有一些统一的重复操作。

现在可以将基类对内容的操作解耦出来,方便配置管理。而且我们封装了一个 Activity 基类后,通常会再封装一个相同功能的 Fragment 基类。这两个基类会有很多相同的操作,我们解耦后就能很容易复用,后续如果要修改也只是改一份代码。

用法和前面的差不多,不过是创建一个适配器继承 LoadingHelper.ContentAdapter。如果想要使用 Activity 对象,可以在构造方法传入或者通过 contentView 对象获得。

public 

在创建 LoadingHelper 对象时传入 ContentAdapter 对象,就会立即对内容视图进行处理。

new LoadingHelper(

终极用法

LoadingHelper 可以解耦 loading 界面,解耦标题栏,解耦内容的重复操作,因为最初封装的目的就是想将视图层的常见重复代码进行深度解耦。

下面分享一下个人结合了本库的特性所封装的 BaseActivityBaseFragment ,介绍一下使用 LoadingHelper 对视图层进行封装能达到怎样的效果。

首先配置默认的适配器,不然后续使用可能会因为找不到适配器报错。

public 

然后就能继承 BaseActivity 进行使用。

public 

当需要对该页面的样式进行定制时,只需增加少量代码。

public 

不是什么复杂的封装,主要是结合了些个人觉得比较好的用法。比如保留重载了原有的 setContentView() 方法,通过布局和控件 id 来确定 contentView,然后用 showContentView() 方法展示出来。前面 set 了后面 show,代码阅读起来也很合理。如果想将一个 Activity 修改成 Fragment,只需把继承 BaseActivity 改成继承 BaseFragment ,因为两个基类的用法保持了一致。

上面的用法只是额外需要三个类,代码并不多,但用起来方便很多。大家也可以作为参考或根据自己的理解和使用习惯进行封装。

感谢

  • luckbilly/Gloading 站在了巨人肩膀上优化了本库,非常感谢! 该库给了我很多启发,我个人花了很多的时间也摸索出用适配器封装比较好,实现原理和思路都是类似的,但是该库居然用不到 200 行代码来实现。当时我写的代码量是这个的数倍,因为有点贪什么功能都想做,而且为了一些个人使用习惯增加了不少代码。后面明确了定位,做了大量的减法。最终优化成用一个 200 多行 Kotlin 代码的工具实现了原有的核心功能,同时保证了灵活性和易用性。

  • drakeet/MultiType 个人一直在使用的列表库,参考了该库注册配置多适配器的思想和用法。原本用法是只实现一个适配器,使用方式更类似 RecyclerView,学习成本更低。不过综合考虑后觉得还是拆分多个适配器使用起来更加灵活方便。

总结

本文讲述了一些管理 loading 界面的方案,分析了一些存在的不足。重点介绍了能同时管理 loading 界面和标题栏的工具 LoadingHelper,相对于同类型的 loading 库,该有的功能都有,还能解耦标题栏和解耦对内容的重复操作,能够进一步解耦视图层。还分享了结合本库封装的 BaseActivityBaseFragment 示例,展示了结合本库对基类进行封装使用能达到怎么样的效果。

如果你觉得本库还不错的话希望能给个 star 支持一下哦~

推荐阅读程序员增加收入实用指南ConcurrentHashMap能否保证绝对的线程安全?面品即人品,匿名diss一些人

编程·思维·职场
欢迎扫码关注

85259280a7786f65cbf762cda78dc4e1.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值