android使用DataBinding来设置空状态
写在前面
在平时的开发之中,我们需要对于数据加载的情况进行展示:
- 空数据
- 网络异常
- 加载中等等情况
现在设置页面状态的方式有多种,由于笔者近期一直在使用databinding,而数据绑定通过改变模型来展示view的方式和状态页的设置也满契合的。
所以这里就讲讲使用databinding来设置android中的各种状态页。很简单,先看看效果
首先
在app的build.gradle文件中开启databinding
android{ ... databinding { enabled = true } }
我们先定义一些用于状态的注解emptystate
/** * 页面描述:空状态 * <p> * created by ditclear on 2017/2/24. */ @intdef({normal, progress, empty, net_error, not_available}) @retention(retentionpolicy.source) public @interface emptystate { int normal = -1; //正常 int progress = -2;//显示进度条 int empty = 11111; //列表数据为空 int net_error = 22222; //网络未连接 int not_available = 33333; //服务器不可用 //...各种页面的空状态,可以自己定义、添加 }
再自定义一个异常emptyexception用于显示我们需要的状态信息
/** * 页面描述:异常 * <p> * created by ditclear on 2017/3/5. */ public class emptyexception extends exception { private int code; public emptyexception(@emptystate int code) { super(); this.code = code; } @emptystate public int getcode() { return code; } public void setcode(@emptystate int code) { this.code = code; } }
现在,大多数展示状态页的控件都会提供
- 加载中的进度条
- 错误信息
- 空状态
- ...
所以我们的目标也是显示这些
布局
以数据绑定的形式进行布局,使用statemodel来控制状态页展示的消息
<?xml version="1.0" encoding="utf-8"?> <layout xmlns:android="http://schemas.android.com/apk/res/android" > <data> <import type="android.view.view"/> <variable name="statemodel" type="com.ditclear.app.state.statemodel"/> </data> <relativelayout android:id="@+id/rv_empty_view" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@color/background" android:clickable="true" android:focusableintouchmode="true" android:visibility="@{statemodel.empty?view.visible:view.gone}"> <android.support.v4.widget.contentloadingprogressbar style="?android:attr/progressbarstyle" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerinparent="true" android:visibility="@{statemodel.progress?view.visible:view.gone}"/> <linearlayout android:layout_width="match_parent" android:layout_height="match_parent" android:layout_alignparentbottom="true" android:layout_alignparentleft="true" android:layout_alignparentstart="true" android:gravity="center" android:orientation="vertical" android:visibility="@{statemodel.progress?view.invisible:view.visible}"> <imageview android:id="@+id/none_data" android:layout_width="345dp" android:layout_height="180dp" android:scaletype="fitcenter" android:src="@{statemodel.emptyiconres}"/> <textview android:layout_width="wrap_content" android:layout_height="25dp" android:layout_below="@+id/none_data" android:layout_centerhorizontal="true" android:text="@{statemodel.currentstatelabel}" android:textsize="16sp"/> </linearlayout> </relativelayout> </layout>
布局文件中有几个方法
- empty 用于控制状态页是显示还是隐藏,数据加载正常(即状态为normal)的时候隐藏,否则展示
- isprogress 是否显示加载中,如果显示进度条(即状态为progress),就隐藏异常页
- emptyiconres 显示状态的图片信息
- currentstatelabel 显示状态的文字消息
我们定义状态的viewmodel ,就叫statemodel,来控制状态
/** * 页面描述:状态页面设置模型 * <p> * created by ditclear on 2017/2/24. */ public class statemodel extends baseobservable { private context mcontext = myapp.instance(); @emptystate private int emptystate = emptystate.normal; private boolean empty; public int getemptystate() { return emptystate; } /** * 设置状态 * * @param emptystate */ public void setemptystate(@emptystate int emptystate) { this.emptystate = emptystate; notifychange(); } /** * 显示进度条 * * @return */ public boolean isprogress() { return this.emptystate == emptystate.progress; } /** * 根据异常显示状态 * * @param e */ public void bindthrowable(throwable e) { if (e instanceof emptyexception) { @emptystate int code = ((emptyexception) e).getcode(); setemptystate(code); } } public boolean isempty() { return this.emptystate != emptystate.normal; } /** * 空状态信息 * * @return */ @bindable public string getcurrentstatelabel() { switch (emptystate) { case emptystate.empty: return mcontext.getstring(r.string.no_data); case emptystate.net_error: return mcontext.getstring(r.string.please_check_net_state); case emptystate.not_available: return mcontext.getstring(r.string.server_not_avaliabe); default: return mcontext.getstring(r.string.no_data); } } /** * 空状态图片 * * @return */ @bindable public drawable getemptyiconres() { switch (emptystate) { case emptystate.empty: return contextcompat.getdrawable(mcontext, r.drawable.ic_visibility_off_green_400_48dp); case emptystate.net_error: return contextcompat.getdrawable(mcontext, r.drawable.ic_signal_wifi_off_green_400_48dp); case emptystate.not_available: return contextcompat.getdrawable(mcontext, r.drawable.ic_cloud_off_green_400_48dp); default: return contextcompat.getdrawable(mcontext, r.drawable.ic_visibility_off_green_400_48dp); } } }
很普通的视图模型,主要有几个用于判断状态显示的方法
- bindthrowable 根据异常显示状态
- setemptystate 方法用来设置当前的状态,通过notifychange来通知布局文件改变
下面讲讲实际运用:
在activity或者fragment布局中,添加状态页的布局
<?xml version="1.0" encoding="utf-8"?> <layout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto"> <data> <import type="android.view.view"/> <variable name="statemodel" type="com.ditclear.app.state.statemodel"/> </data> <com.ditclear.app.scrollchildswiperefreshlayout android:id="@+id/refresh_layout" android:layout_width="match_parent" android:layout_height="match_parent"> <relativelayout android:id="@+id/container" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <android.support.v4.widget.nestedscrollview android:layout_width="match_parent" android:layout_height="match_parent" android:fillviewport="false" android:overscrollmode="always" android:visibility="@{statemodel.empty?view.gone:view.visible}"> <textview android:id="@+id/content_tv" android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center"/> </android.support.v4.widget.nestedscrollview> <include layout="@layout/widget_layout_empty" app:statemodel="@{statemodel}"/> </relativelayout> </com.ditclear.app.scrollchildswiperefreshlayout> </layout>
最后在activity或者fragment中我们只需要通过state.bindthrowable()和state.setemptystate()方法便可以轻松设置各种各样的状态。
loaddata().subscribe(new subscriber<list<contributor>>() { @override public void onstart() { super.onstart(); if (!mmainbinding.refreshlayout.isrefreshing()) { mstatemodel.setemptystate(emptystate.progress); } } @override public void oncompleted() { mstatemodel.setemptystate(emptystate.normal); } @override public void onerror(throwable e) { mmainbinding.refreshlayout.setrefreshing(false); mstatemodel.bindthrowable(e); toast.maketext(mainactivity.this, mstatemodel.getcurrentstatelabel(), toast.length_short).show(); } @override public void onnext(list<contributor> contributors) { mmainbinding.refreshlayout.setrefreshing(false); if (contributors == null || contributors.isempty()) { onerror(new emptyexception(emptystate.empty)); } else { mmainbinding.contenttv.settext(contributors.tostring()); } } });
写在最后
对于要使用数据来控制视图状态的,使用databinding实在是一个事半功倍的方式。而且也十分容易理解。
最后demo地址:statebinding_jb51.rar
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
上一篇: 迅雷极速版设置关闭悬浮窗和开机不启动的方法图文介绍
下一篇: IBM 笔记本T61开机不稳定维修一例