为Ability添加加载状态
加载成功 | 加载失败 点击重试 |
加载成功 无数据 |
个别页面使用特殊的Loading视图 |
---|---|---|---|
![]() |
![]() |
![]() |
![]() |
为Component添加加载状态
用于Slice | 用于ScrollView | 用于ListContainer |
---|---|---|
![]() |
![]() |
![]() |
Loading动画几乎每个Hos Hap中都有。
一般在需要用户等待的场景,显示一个Loading动画可以让用户知道Hap正在加载数据,而不是程序卡死,从而给用户较好的使用体验。
同样的道理,当加载的数据为空时显示一个数据为空的视图、在数据加载失败时显示加载失败对应的UI并支持点击重试会比白屏的用户体验更好一些。
加载中、加载失败、空数据的UI风格,一般来说在Hap内的所有页面中需要保持一致,也就是需要做到全局统一。
LoadingComponent
)BaseAbility/BaseSlice
中封装LoadingComponent
的初始化逻辑,并封装加载状态切换时的UI显示逻辑,暴露给子类以下方法:
void showLoading();
//调用此方法显示加载中的动画void showLoadFailed();
//调用此方法显示加载失败界面void showEmpty();
//调用此方法显示空页面void onClickRetry();
//子类中实现,点击重试的回调方法BaseAbility/BaseSlice
的子类中可通过上一步的封装比较方便地使用加载状态显示功能这种使用方式耦合度太高,每个页面的布局文件中都需要添加LoadingComponent
,使用起来不方便而且维护成本较高,一旦UI设计师需要更改布局,修改起来成本较高。
LoadingComponent
)LoadingUtil
)来管理LoadingComponent
,不同状态显示不同的UI(或者在多个Component之间切换显示)BaseAbility/BaseSlice
中对LoadingUtil
的使用进行封装,暴露给子类以下方法:
void showLoading();
//调用此方法显示加载中的动画void showLoadFailed();
//调用此方法显示加载失败界面void showEmpty();
//调用此方法显示空页面void onClickRetry();
//子类中实现,点击重试的回调方法abstract int getContainerId();
//子类中实现,LoadingUtil
动态创建LoadingComponent
并添加到该方法返回id对应的控件中BaseAbility/BaseSlice
的子类中可通过上一步的封装比较方便地使用加载状态显示功能这种封装的好处是通过封装动态地创建LoadingComponent
并添加到指定的父容器中,让具体页面无需关注LoadingComponent
的实现,只需要指定在哪个容器中显示即可,很大程度地进行了解耦。如果公司只在一个Hap中使用,这基本上就够了。
但是,这种封装方式还是存在耦合:页面与它所使用的LoadingComponent
仍然存在绑定关系。如果需要复用到其它Hap中,因为每个App的UI风格可能不同,对应的LoadingComponent
布局也可能会不一样,要想复用必须先将页面与LoadingComponent
解耦。
LoadingComponent
可切换,且不需要改动页面代码LoadingComponent
的显示区域(例如导航栏Title不希望被LoadingComponent
覆盖)Gloading是一个基于Adapter思路实现的深度解耦Hap中全局LoadingComponent的轻量级工具(只有一个java文件,不到300行,其中注释占100+行,aar仅6K)
1、 依赖
allprojects{
repositories{
mavenCentral()
}
}
implementation 'io.openharmony.tpc.thirdlib:Gloading:1.0.3'
2、 创建Adapter
,在getComponent
方法中实现创建各种状态视图(加载中、加载失败、空数据等)的逻辑
Gloading不侵入UI布局,完全由用户自定义
public class GlobalAdapter implements Gloading.Adapter {
@Override
public Component getComponent(Gloading.Holder holder, Component convertComponent, int status) {
GlobalLoadingStatusView loadingStatusView = null;
//convertComponent为可重用的布局
//Holder中缓存了各状态下对应的View
// 如果status对应的Component为null,则convertComponent为上一个状态的Component
// 如果上一个状态的Component也为null,则convertComponent为null
if (convertComponent != null && convertComponent instanceof GlobalLoadingStatusView) {
loadingStatusView = (GlobalLoadingStatusView) convertComponent;
}
if (loadingStatusView == null) {
loadingStatusView = new GlobalLoadingStatusView(holder.getContext(), holder.getRetryTask());
}
loadingStatusView.setStatus(status);
return loadingStatusView;
}
class GlobalLoadingStatusView extends DependentLayout {
public GlobalLoadingStatusView(Context context, Runnable retryTask) {
super(context);
//初始化LoadingComponent
//如果需要支持点击重试,在适当的时机给对应的控件添加点击事件
}
public void setStatus(int status) {
//设置当前的加载状态:加载中、加载失败、空数据等
//其中,加载失败可判断当前是否联网,可现实无网络的状态
// 属于加载失败状态下的一个分支,可自行决定是否实现
}
}
}
3、 初始化Gloading
的默认Adapter
Gloading.initDefault(new GlobalAdapter());
4、在需要使用LoadingComponent
的地方获取Holder
//在Ability中显示, 父容器为: mLayout
Gloading.Holder holder = Gloading.getDefault().wrap(ability, mLayout);
//需要支持加载失败后点击重试
Gloading.Holder holder = Gloading.getDefault().wrap(ability, mLayout).withRetry(retryTask);
or
//为某个Component显示加载状态
//Gloading会自动创建一个FrameLayout,将Component包裹起来,LoadingComponent也显示在其中
Gloading.Holder holder = Gloading.getDefault().wrap(component);
//需要支持加载失败后点击重试
Gloading.Holder holder = Gloading.getDefault().wrap(component).withRetry(retryTask);
4.1 如果父容器为 DependentLayout
,用cover可以保持与同级其它控件之间的关联关系
Gloading.Holder holder = Gloading.getDefault().cover(component);
//或
Gloading.Holder holder = Gloading.getDefault().cover(component).withRetry(retryTask);
5、 使用Holder
来显示各种加载状态
//显示加载中的状态,通常是显示一个加载动画
holder.showLoading()
//显示加载成功状态(一般是隐藏LoadingComponent)
holder.showLoadSuccess()
//显示加载失败状态
holder.showFailed()
//数据加载完成,但数据为空
holder.showEmpty()
//如果以上默认提供的状态不能满足使用,可使用此方法调用其它状态
holder.showLoadingStatus(status)
6、 兼容多App场景下的页面、Component的复用
每个Hap的LoadingComponent
可能会不同,只需为每个Hap提供不同的Adapter
,不同App调用不同的Gloading.initDefault(new GlobalAdapter());
,具体页面中的使用代码无需改动。
//设置为true时Logcat会输出日志
Gloading.debug(trueOrFalse);
Gloading.Holder holder = Gloading.getDefault().wrap(activity);
改为
//需要将父布局传入
Gloading.Holder holder = Gloading.getDefault().wrap(ability, mLayout);
通过DevEco studio,并下载SDK 将项目中的build.gradle文件中dependencies→classpath版本改为对应的版本(即你的IDE新建项目中所用的版本)
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。