问题由来
我们在项目中开发界面UI的时候,肯定遇到过要根据不同的返回值类型展示相应UI的操作。如我们的网络请求,我们在无网络的时候会显示暂无数据界面,在网络数据返回异常的情况下会展示网络异常请重试的UI。
当遇到上面的需求我们通常是怎样做的呢?
我想肯定有一部分人是将网络有关的UI写在了一个layout文件中,然后在别的布局中进行引用。但是有没有人思考过这样写好不好。
好我们接下来看,如果后期需求要改变某一个页面的无数据样式,我们怎么办?难道再去写一个网络的layout,把原来引用的地方替换为我们新写的layout,这样做真的好吗?让我们来看一下,如果新的UI改动比较大,这个时候我们就可能需要对activity中的代码进行大修改,这样做明显是有问题的,先不说新增的代码怎么样,单看修改原先的代码这一项就不行,修改原先的代码逻辑可能会带来一些未知的bug。既然有这样的问题那我们该怎样做呢?
一种思路
在这我先来说一下自己的想法,我们可以将不同的view拆分出去,然后以策略的方式加载进来。具体做法:我们将上面的网络错误和无数据view都单独提出来,然后我们使用tag建立一个map集合。如下图
代码中我们先写好网络错误和无数据的View的布局和代码如下:
/**
* 网络错误
*/
public class NetError extends BaseView<Object, NetErrorBinding> {
public NetError(Context context, Object data, ViewGroup parent) {
super(context, data, parent);
}
@Override
public int getLayoutId() {
return R.layout.net_error;
}
@Override
protected void initView(View view, boolean isUpdate) {
//初始化view
if (!isUpdate) {
mBinding.tvResponse.setText("请求失败 稍后重试");
}
}
@Override
protected void initListener(View view, boolean isUpdate) {
if (!isUpdate) {
view.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {//重新刷新数据,通过data中传过来的接口进行回调
}
});
}
}
@Override
protected void initViewConfigure(HashMap<String, Class> viewConfigure) {
}
@Override
protected ConbinationBuilder combinationViewBuilder() {
return null;
}
}
/**
* 暂无数据
*/
public class NoData extends BaseView<Object, NetNoDataBinding> {
public NoData(Context context, Object data, ViewGroup parent) {
super(context, data, parent);
}
@Override
public int getLayoutId() {
return R.layout.net_no_data;
}
@Override
protected void initView(View view, boolean isUpdate) {
if (!isUpdate) {
mBinding.tvResponse.setText("暂无数据");
}
}
@Override
protected void initListener(View view, boolean isUpdate) {
}
@Override
protected void initViewConfigure(HashMap<String, Class> viewConfigure) {
}
@Override
protected ConbinationBuilder combinationViewBuilder() {
return null;
}
}
在这里我们的两个view都需要继承自BaseView接口,BaseView中的泛型第一个是要传入的数据类型(数据类型可以是任意类型),第二个是layout对应的databinding。初始化完我们的两个view,然后在activity中初始化我们的map集合
mTagMapView[Constant.NET_ERROR] = NetError::class.java
mTagMapView[Constant.NET_NO_DATA] = NoData::class.java
初始化点击事件:
fun netError(v: View?) {
//第三个参数是要传入的数据
sv_view.setData(Constant.NET_ERROR, mTagMapView,"")
}
fun noData(v: View?) {
sv_view.setData(Constant.NET_NO_DATA, mTagMapView,"")
}
接下来让我们看看效果
在这里实现UI的切换效果还是很方便的
尤其当我们面临复杂UI的切换时,这样写的特点是第一:当有新的状态时我们不需要去修改原来的UI,而是直接新建一个Ui就可以了,从而避免了修改原先代码带来的隐患。第二:这样写也是对UI进行了划分,使单个view的操作变得简单,而不是像原先一样所有的逻辑都写在了一个页面中,不易阅读和维护。
面对上面的问题,这是我的解决方法,可以用在根据不同类型显示不同View的地方也可以用在复杂view的拆分上。有兴趣的可以去我的git上下载源码看看
。