前情回顧:
1.WanAndroid實戰(zhàn)——首頁Banner
3.WanAndroid實戰(zhàn)——內(nèi)容顯示
前面一直都是在理想環(huán)境(有網(wǎng)絡(luò)連接)下的狀態(tài),當沒有網(wǎng)絡(luò)的時候,將無法獲取數(shù)據(jù)配喳,此時界面顯示不友好锌奴,今天來處理這個問題螃成。效果圖先行:
在關(guān)閉Wi-Fi時舶斧,打開應(yīng)用今缚,會顯示指定的布局调窍,點擊“重新加載”,會刷新數(shù)據(jù),同時對SmartRefereshLayout的Header和Footer做了修改莽龟,當沒有網(wǎng)絡(luò)的時候顯示“刷新失敗”蠕嫁,“加載失敗”,更準確的進行了顯示轧房。
無網(wǎng)絡(luò)時的error頁面
在首次進入時拌阴,因為機器沒有連接網(wǎng)絡(luò),所以無法獲取到數(shù)據(jù)奶镶,此時應(yīng)該顯示error頁面迟赃。最近看文章時看到了布局優(yōu)化方面的內(nèi)容,有介紹到ViewStub
厂镇,剛好這里可以使用纤壁,也可以練練手。
1.在主頁布局文件activity_main.xml
根布局中添加ViewStub
<ViewStub
android:id="@+id/net_error_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout="@layout/net_error"
/>
關(guān)于ViewStub是如何實現(xiàn)布局優(yōu)化的捺信,和include又有哪些不同酌媒,這些知識大家可以自行學習(我是偷偷的學過了),效率這種東西迄靠,能優(yōu)化的還是優(yōu)化吧秒咨,養(yǎng)成好的習慣,
net_error.xml
為真正顯示的內(nèi)容掌挚。
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<TextView
android:id="@+id/net_error"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:drawableTop="@drawable/net_error"
android:drawablePadding="@dimen/net_error_drawable_padding"
android:gravity="center"
android:text="@string/net_error_message"
android:textSize="@dimen/common_text_size"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
/>
<TextView
android:id="@+id/net_refresh"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/net_refresh_margin_top"
android:background="@drawable/refresh_background"
android:clickable="true"
android:focusable="true"
android:gravity="center"
android:paddingStart="@dimen/net_refresh_padding_start_and_end"
android:paddingTop="@dimen/net_refresh_padding_top_and_bottom"
android:paddingEnd="@dimen/net_refresh_padding_start_and_end"
android:paddingBottom="@dimen/net_refresh_padding_top_and_bottom"
android:text="@string/net_error_refresh"
android:textColor="@color/net_refresh_color"
android:textSize="@dimen/common_text_size"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@id/net_error"/>
</android.support.constraint.ConstraintLayout>
net_error
的textView中的圖片數(shù)據(jù)加載失敗是在iconfont中下載的雨席,里面圖標很多,大家可以選擇自己認為好看的來使用吠式;net_refresh
的background是自己寫的一個shape陡厘,也是很簡單的,其它就是普通的內(nèi)容特占,效果如下:
2.在MainActivity.java
中添加邏輯處理
啟動過程的流程如下圖所示糙置,根據(jù)圖示,可以很清楚的來敲代碼了是目。
在初始化數(shù)據(jù)時判斷網(wǎng)絡(luò)連接谤饭,根據(jù)網(wǎng)絡(luò)狀況進行處理,核心代碼如下:
/**
* <p>獲取數(shù)據(jù)</p>
*/
private void initData() {
if (NetworkUtils.isConnected()) {
mPresenter.loadBanner();
mPresenter.refreshArticle();
showNormal();
}
else {
showNetError();
}
}
/**
* <p>顯示無網(wǎng)絡(luò)時的布局</p>
*/
private void showNetError() {
if (mNetErrorLayout != null) {
mMainBanner.setVisibility(View.GONE);
mRefreshLayout.setVisibility(View.GONE);
mNetErrorLayout.setVisibility(View.VISIBLE);
return;
}
mMainBanner.setVisibility(View.GONE);
mRefreshLayout.setVisibility(View.GONE);
mNetErrorLayout = findViewById(R.id.net_error_layout);
View view = mNetErrorLayout.inflate();
mNetRefresh = view.findViewById(R.id.net_refresh);
mNetRefresh.setOnClickListener(v -> {
if (NetworkUtils.isConnected()) {
mPresenter.refreshArticle();
mPresenter.loadBanner();
showNormal();
}
else {
showNetErrorToast();
}
});
}
/**
* <p>網(wǎng)絡(luò)錯誤的toast提示</p>
*/
private void showNetErrorToast() {
ToastUtils.setBgColor(getResources().getColor(R.color.toast_bg_color, null));
ToastUtils.setMsgColor(getResources().getColor(R.color.toast_text_color, null));
ToastUtils.showShort(R.string.net_error_toast);
}
/**
* <p>顯示正常內(nèi)容</p>
*/
private void showNormal() {
if (mNetErrorLayout != null) {
mNetErrorLayout.setVisibility(View.GONE);
}
mMainBanner.setVisibility(View.VISIBLE);
mRefreshLayout.setVisibility(View.VISIBLE);
}
無網(wǎng)絡(luò)時Header和Footer的顯示
在沒有網(wǎng)絡(luò)的情況下懊纳,刷新和加載怎么能成功呢网持,所以需要在刷新和加載的監(jiān)聽中添加處理,核心代碼就是在加載失敗的時候傳入false參數(shù)长踊,框架就會顯示“失敗”了。
refreshLayout.finishRefresh(false);
refreshLayout.finishLoadMore(false);
有網(wǎng)絡(luò)連接萍倡,但是獲取數(shù)據(jù)失敗
無網(wǎng)絡(luò)連接的情況比較好處理身弊,如果連接到了網(wǎng)絡(luò),但是并無法獲取數(shù)據(jù)(比如連接到局域網(wǎng)),就比較惡心了阱佛,因為不知道是什么原因?qū)е碌臄?shù)據(jù)無法獲得帖汞,因此需要進行特殊處理。
自動重連是我能想到的一種處理方法凑术,但是又不能無限重連翩蘸,參考了大神的文章,我的處理方法直接貼代碼淮逊。
@Override
public void loadBanner() {
mModel.loadBanner()
.retryWhen(throwableObservable -> throwableObservable.flatMap((Function<Throwable,
ObservableSource<?>>) throwable -> {
LogUtils.d("exception:" + throwable.toString());
if (throwable instanceof IOException) {
LogUtils.d("IOException need retry");
if (mBannerRetryCount < MAX_RETRY_COUNT) {
mBannerRetryCount++;
LogUtils.d("mBannerRetryCount:" + mBannerRetryCount);
int waitRetryTime = 3000 + mBannerRetryCount * 1000;
LogUtils.d("wait time: " + waitRetryTime);
return Observable.just(1).delay(waitRetryTime, TimeUnit.MILLISECONDS);
}
else {
return Observable.error(new Throwable("retry time reach the max count"));
}
}
else {
return Observable.error(new Throwable("not IOException"));
}
}))
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<BannerBean>() {
@Override
public void onSubscribe(Disposable d) {
mCompositeDisposable.add(d);
}
@Override
public void onNext(BannerBean bean) {
if (isViewAttached()) {
getView().loadBanner(bean);
}
}
@Override
public void onError(Throwable e) {
LogUtils.d("banner onError()");
if (isViewAttached()) {
getView().onError(e);
}
}
@Override
public void onComplete() {
LogUtils.d("banner onComplete()");
}
});
}
關(guān)鍵代碼就是調(diào)用了retryWhen催首,這里面的處理邏輯就是當異常為IO異常且重連次數(shù)小于最大重試次數(shù)時,進行重連泄鹏,并且每一次重連的等待時間都有所增加郎任。這個邏輯可以根據(jù)自己的實際情況進行修改。
即使采用重連的方法备籽,仍然有可能獲取不到數(shù)據(jù)舶治,這里可以選擇顯示一個類似于“無數(shù)據(jù)”的頁面,也可以不做處理车猬,畢竟還有下拉刷新等可以重新加載數(shù)據(jù)霉猛。最近又開始忙了,后面的內(nèi)容估計要延期了珠闰,下面計劃加動態(tài)網(wǎng)絡(luò)權(quán)限請求惜浅,而不是直接賦予網(wǎng)絡(luò)權(quán)限,因為CTS認證有這個要求铸磅。