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