android使用DataBinding來(lái)設(shè)置空狀態(tài)
寫在前面
在平時(shí)的開發(fā)之中,我們需要對(duì)于數(shù)據(jù)加載的情況進(jìn)行展示:
- 空數(shù)據(jù)
- 網(wǎng)絡(luò)異常
- 加載中等等情況
現(xiàn)在設(shè)置頁(yè)面狀態(tài)的方式有多種,由于筆者近期一直在使用databinding,而數(shù)據(jù)綁定通過(guò)改變模型來(lái)展示view的方式和狀態(tài)頁(yè)的設(shè)置也滿契合的。
所以這里就講講使用databinding來(lái)設(shè)置android中的各種狀態(tài)頁(yè)。很簡(jiǎn)單,先看看效果
首先
在app的build.gradle文件中開啟databinding
android{ ... dataBinding { enabled = true } }
我們先定義一些用于狀態(tài)的注解EmptyState
/** * 頁(yè)面描述:空狀態(tài) * <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;//顯示進(jìn)度條 int EMPTY = 11111; //列表數(shù)據(jù)為空 int NET_ERROR = 22222; //網(wǎng)絡(luò)未連接 int NOT_AVAILABLE = 33333; //服務(wù)器不可用 //...各種頁(yè)面的空狀態(tài),可以自己定義、添加 }
再自定義一個(gè)異常EmptyException用于顯示我們需要的狀態(tài)信息
/** * 頁(yè)面描述:異常 * <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; } }
現(xiàn)在,大多數(shù)展示狀態(tài)頁(yè)的控件都會(huì)提供
- 加載中的進(jìn)度條
- 錯(cuò)誤信息
- 空狀態(tài)
- ...
所以我們的目標(biāo)也是顯示這些
布局
以數(shù)據(jù)綁定的形式進(jìn)行布局,使用StateModel來(lái)控制狀態(tài)頁(yè)展示的消息
<?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>
布局文件中有幾個(gè)方法
- empty 用于控制狀態(tài)頁(yè)是顯示還是隱藏,數(shù)據(jù)加載正常(即狀態(tài)為NORMAL)的時(shí)候隱藏,否則展示
- isProgress 是否顯示加載中,如果顯示進(jìn)度條(即狀態(tài)為PROGRESS),就隱藏異常頁(yè)
- emptyIconRes 顯示狀態(tài)的圖片信息
- currentStateLabel 顯示狀態(tài)的文字消息
我們定義狀態(tài)的ViewModel ,就叫StateModel,來(lái)控制狀態(tài)
/** * 頁(yè)面描述:狀態(tài)頁(yè)面設(shè)置模型 * <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; } /** * 設(shè)置狀態(tài) * * @param emptyState */ public void setEmptyState(@EmptyState int emptyState) { this.emptyState = emptyState; notifyChange(); } /** * 顯示進(jìn)度條 * * @return */ public boolean isProgress() { return this.emptyState == EmptyState.PROGRESS; } /** * 根據(jù)異常顯示狀態(tài) * * @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; } /** * 空狀態(tài)信息 * * @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); } } /** * 空狀態(tài)圖片 * * @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); } } }
很普通的視圖模型,主要有幾個(gè)用于判斷狀態(tài)顯示的方法
- bindThrowable 根據(jù)異常顯示狀態(tài)
- setEmptyState 方法用來(lái)設(shè)置當(dāng)前的狀態(tài),通過(guò)notifyChange來(lái)通知布局文件改變
下面講講實(shí)際運(yùn)用:
在activity或者fragment布局中,添加狀態(tài)頁(yè)的布局
<?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中我們只需要通過(guò)state.bindThrowable()和state.setEmptyState()方法便可以輕松設(shè)置各種各樣的狀態(tài)。
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()); } } });
寫在最后
對(duì)于要使用數(shù)據(jù)來(lái)控制視圖狀態(tài)的,使用databinding實(shí)在是一個(gè)事半功倍的方式。而且也十分容易理解。
最后demo地址:StateBinding_jb51.rar
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Android實(shí)現(xiàn)QQ側(cè)滑(刪除、置頂?shù)?功能
這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)QQ側(cè)滑刪除、置頂?shù)裙δ?,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-12-12簡(jiǎn)單掌握Android Widget桌面小部件的創(chuàng)建步驟
這篇文章主要介紹了簡(jiǎn)單掌握Android Widget桌面小部件的創(chuàng)建步驟,Widget一般采用web前端技術(shù)進(jìn)行開發(fā),需要的朋友可以參考下2016-03-03Flutter permission_handler 權(quán)限插件的使用詳解
這篇文章主要介紹了Flutter permission_handler 權(quán)限插件的使用,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-04-04listView的item中有checkbox,導(dǎo)致setOnItemClick失效的原因及解決辦法
這篇文章主要介紹了listView的item中有checkbox,導(dǎo)致setOnItemClick失效的原因及解決辦法,需要的朋友可以參考下2017-01-01Android 8.0升級(jí)不跳轉(zhuǎn)應(yīng)用安裝頁(yè)面的解決方法
這篇文章主要為大家詳細(xì)介紹了Android 8.0升級(jí)不跳轉(zhuǎn)應(yīng)用安裝頁(yè)面的解決方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-06-06淺談Android開發(fā)中ListView控件性能的一些優(yōu)化方法
這篇文章主要介紹了Android開發(fā)中ListView控件性能的一些優(yōu)化方法,需要的朋友可以參考下2016-01-01AndroidApk混淆編譯時(shí),報(bào)告java.io.IOException...錯(cuò)誤解決辦法
這篇文章主要介紹了 AndroidApk混淆編譯時(shí),報(bào)告Error:Execution failed for task ‘:gviews:transformClassesAndResourcesWithProguardForRelease’.錯(cuò)誤解決辦法的相關(guān)資料,需要的朋友可以參考下2017-03-03Android實(shí)現(xiàn)笑臉進(jìn)度加載動(dòng)畫
這篇文章主要介紹了Android實(shí)現(xiàn)笑臉進(jìn)度加載動(dòng)畫的方法,幫助大家更好的理解和學(xué)習(xí)使用Android,感興趣的朋友可以了解下2021-05-05Flutter實(shí)現(xiàn)不同縮放動(dòng)畫效果詳解
這篇文章主要為大家詳細(xì)介紹了Flutter利用不同組件(ScaleTransition、SizeTransition、AnimatedSize和AnimatedBuilder)實(shí)現(xiàn)不同縮放動(dòng)畫效果,感興趣的可以動(dòng)手嘗試一下2022-06-06