背景和问题
在app后sdk开发过程中,如果有遇到延时任务的时候,往往需要添加一个通用的loading控件用来展示给用户,一来为了提示用户当前有耗时的操作,二来降低用户的等待感提升用户体验。
所以,一个通用的loading组件就应运而生。
但似乎并不是所有人都会友好地去开发这样的控件。
举个栗子,以下是某个项目源码:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<RelativeLayout
android:id="@+id/content"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@id/title_bar">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<com.creditapply.custom_view.RoundCornerImageView
android:id="@+id/iv_credit_img"
android:layout_width="300dp"
android:layout_height="185dp"
android:layout_gravity="center_horizontal"
android:layout_marginBottom="18dp"
android:layout_marginLeft="25dp"
android:layout_marginRight="25dp"
android:layout_marginTop="20dp"
android:src="@drawable/card_default" />
<TextView
android:id="@+id/tv_credit_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginRight="@dimen/credit_margin_ege"
android:maxLines="1"
android:text="银行卡名称"
android:textColor="@color/black"
android:textSize="@dimen/theme_txt_size_17" />
</LinearLayout>
<TextView
android:id="@+id/bottomButton"
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_alignParentBottom="true"
android:background="@drawable/btn_main_blue"
android:gravity="center"
android:text="立即申请"
android:textColor="#ffffff"
android:textSize="@dimen/theme_txt_size_16"
android:visibility="visible" />
</RelativeLayout>
<com.app.common.widgets.LoadRalatedView
android:id="@+id/load_failure_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@id/title_bar"
android:layout_centerInParent="true" />
</RelativeLayout>
由于视图结构相对简单,所以代码看上去没那么糟糕,很便于阅读。事实真是这样吗?(事实是我删了一堆代码,只留了几个元素测试)
我们来打开Android studio的priview
几乎什么都看不到,这并不是一种友好的体验。
1.虽然封装了LoadRalatedView(loading的控件),但是必须要放于顶层,加载时显示,但是把真实视图给遮挡了。
2.代码的冗余,几乎每个需要网络加载的地方,都需要手动去增加这样的代码。
3.直接的结果导致开发者不能专注真正的业务视图。
期望
我希望开发者能够完成沉浸在业务视图开发中而不是在xml中主动添加一个loadingView。
基于这个目的,我首先想到是在java层中去动态实例化一个这样的控件,那么我们所要做的就是去选取一个这样的view(命名为contentView,就是被user能看到的view),它能够被控件持有并占据所在的位置,这样可以主动的去展示contentView或者loadingview或者netWorkErroView,甚至还能对这些view做深度的定制。
基于这个想法可以继续的延伸。大多数情况,给用户展示的这个contentView是固定某个,基本是除了titlebar的部分。这样,我们甚至都不用去主动需找这样的一个锚点用于初始化控件,在基类中就可以初始化控件。
于是,我们调用的代码应该是这样的:
getLoadingHelper().showLoadingView();//loading
//执行耗时操作
JTHttpClient.create()
.url(CreditServiceHelper.URL_PREFIX + current_method)
.setSecLevel(JtRequest.PRIVATE_CRYPT)
.build()
.post(NextBeanResult.class)
.subscribe(new DisposableSingleObserver<NextBeanResult>() {
@Override
public void onSuccess(NextBeanResult nextBeanResult) {
getLoadingHelper().showContentView();//showContentView
mInputLayout.reBuildViews(nextBeanResult);
}
@Override
public void onError(Throwable e) {
getLoadingHelper().showNetworkError();//showNetworkError
UIUtil.INSTANCE.showExceptionMsg(e);
}
});
原理和实现
//todo