Android复杂View或者不同状态View拆分的一种思路

点击跳转statusView项目地址

问题由来

我们在项目中开发界面UI的时候,肯定遇到过要根据不同的返回值类型展示相应UI的操作。如我们的网络请求,我们在无网络的时候会显示暂无数据界面,在网络数据返回异常的情况下会展示网络异常请重试的UI。

当遇到上面的需求我们通常是怎样做的呢?

我想肯定有一部分人是将网络有关的UI写在了一个layout文件中,然后在别的布局中进行引用。但是有没有人思考过这样写好不好。

好我们接下来看,如果后期需求要改变某一个页面的无数据样式,我们怎么办?难道再去写一个网络的layout,把原来引用的地方替换为我们新写的layout,这样做真的好吗?让我们来看一下,如果新的UI改动比较大,这个时候我们就可能需要对activity中的代码进行大修改,这样做明显是有问题的,先不说新增的代码怎么样,单看修改原先的代码这一项就不行,修改原先的代码逻辑可能会带来一些未知的bug。既然有这样的问题那我们该怎样做呢?

一种思路

在这我先来说一下自己的想法,我们可以将不同的view拆分出去,然后以策略的方式加载进来。具体做法:我们将上面的网络错误和无数据view都单独提出来,然后我们使用tag建立一个map集合。如下图
Android复杂View或者不同状态View拆分的一种思路
代码中我们先写好网络错误和无数据的View的布局和代码如下:

Android复杂View或者不同状态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;
    }
}

Android复杂View或者不同状态View拆分的一种思路

/**
 * 暂无数据
 */
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,"")
    }

接下来让我们看看效果
Android复杂View或者不同状态View拆分的一种思路
在这里实现UI的切换效果还是很方便的Android复杂View或者不同状态View拆分的一种思路
尤其当我们面临复杂UI的切换时,这样写的特点是第一:当有新的状态时我们不需要去修改原来的UI,而是直接新建一个Ui就可以了,从而避免了修改原先代码带来的隐患。第二:这样写也是对UI进行了划分,使单个view的操作变得简单,而不是像原先一样所有的逻辑都写在了一个页面中,不易阅读和维护。

面对上面的问题,这是我的解决方法,可以用在根据不同类型显示不同View的地方也可以用在复杂view的拆分上。有兴趣的可以去我的git上下载源码看看

上一篇:redis本机能访问 远程不能访问的问题


下一篇:Web移动端项目适配(适用于原生JavaScript,Vue,React等项目中)