android使用DataBinding来设置空状态
作者:ditclear 发布时间:2022-02-06 22:28:35
写在前面
在平时的开发之中,我们需要对于数据加载的情况进行展示:
空数据
网络异常
加载中等等情况
现在设置页面状态的方式有多种,由于笔者近期一直在使用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
来源:http://www.jianshu.com/p/276c8aa80f20#
猜你喜欢
- 什么是Kotlin?Kotlin是一种可以在 Java 虚拟机 (JVM) 上运行的开源编程语言。该语言可以在许多平台上运行。它是一种将面向
- 依赖<dependency> <groupId>com.baomidou</groupId> <a
- 本文实例为大家分享了Java实现二分查找的变种,供大家参考,具体内容如下普通二分查找:先回顾一下普通的二分查找注意:二分查找有这样一个问题:
- 此解决方案是针对window的,因为日志默认保存路径在C盘,linux忽略。学习RocketMQ过程中,总是出现com.alibaba.ro
- 1 MapStruct配置MapStuct的使用非常简单,把对应的jar包引入即可。<properties> &n
- 前言MyBatis 是一款优秀的持久层框架,它支持定制化 SQL、存储过程以及高级映射。MyBatis 避免了几乎所有的 JDBC 代码和手
- Flyway是一款开源的数据库版本管理工具,它更倾向于规约优于配置的方式。第一步:pom.xml添加maven依赖<!-- https
- ErrorPageFilter的实际应用Spring框架错误页过滤器springboot提供了一个ErrorPageFilter,用来处理当
- Java Lambda 源码分析问题:Lambda 表达式是什么?JVM 内部究竟是如何实现 Lambda 表达式的?为什么要这样实现?一、
- 代码如下:using System; using System.Collections.Generic; using S
- 一般情况下在Word中输入的文字都是横向的,今天给大家分享两种方法来设置/更改一个section内的所有文本的方向及部分文本的方向,有兴趣的
- 方法● maxBy:获取流中最大元素;minBy:获取流中最小元素● joining:合并,将流中的元素,以字符串的形式拼接起来● summ
- 本文实例讲述了Android编程实现系统重启与关机的方法。分享给大家供大家参考,具体如下:最近在做个东西,巧合碰到了sharedUserId
- DAO模式是接口的一个典型应用。1. StudenDaoListImpl.java与StudentDaoArrayImpl.java有何不同
- 前言:有时候我们在用Spring Aop面向切面编程,需要获取连接点(JoinPoint)方法参数名、参数值。环境:Mac OSXIntel
- 依赖添加<dependency> <groupId>org.springframework.boot&l
- 安装Jenkins提示:首先Jenkins安装方式有2中,一种是yum安装,另一种是使用war的方式进行安装(war就需要安装tomcat)
- springboot 异常与重定向在spring中,有两个重定向类型:301,永久性跳转302,暂时性跳转默认调用302。1.下面先通过一个
- 在利用C#开发Winform应用程序的时候,我们有可能使用RichTextBox来实现实时显示应用程序日志的功能,日志又分为:一般消息,警告
- ThreadGroup的作用及方法ThreadGroup线程组,java对这个类的描述呢就是“线程组表示一组线程。此外,线程组还可以包括其他