LoadingView解決首次頁面刷新狀態(請求中,無數據,失敗)

引言

1.我們在日常開發中經常會遇到數據加載需要網絡請求的場景,我們通常的做法是用系統提供的ProgressDialog組件
(顯示等待進度的dialog) 但是會有一個不友好的地方(假如網絡出異常了,此時頁面沒有填充數據。此時就要控制頁面 
內一些交互操作,這樣界面中就會多出一大串邏輯控制代碼),有一種解決方案解決上述的缺點,就是界面內部用一個進度條 
遮蓋內容頁面,用邏輯進行控制請求中、請求失敗、無數據等幾種狀態,但是一個app裏面有辣麼多的界面都是這種需求, 
要是每個界面都這樣寫豈不很重複繁瑣。如何簡化呢,封裝起來(*@ο@*) 哇~
2.今天給大家介紹個自定義view組件來解決此問題(ui的效果根據大家自己的需求 自行定製哈)

先來張動態圖=-=
這裏寫圖片描述

需求點

1.這個view需要有一個方法來控制各個狀態的切換
2.可以定製加載進度條的狀態
3.可以定製無數據的頁面
4.加載失敗可以提供刷新操作

實現思路

既然是自定義view,api就得儘量簡潔好理解嘛,我所設想的api
//根據場景切換各個狀態State各種狀態的枚舉(往下看)
public void notifyDataChanged(State state)
//數據加載失敗提供重試的回調
public void setOnRetryListener(OnRetryListener listener)
//設置數據爲null顯示的view
public void setEmptyView(View view)
//重試回調的接口0
public interface OnRetryListener {
        void onRetry();
}

刷新的各種狀態

public enum State {
        ing, error, done, empty
}

api是不是很簡單^_^
接下來貼整個類的代碼(一種不到100行代碼)

package cn.wei.library.widget;

import android.content.Context;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.FrameLayout;

import cn.wei.library.R;


/**
 * LoadingView解決了請求網絡數據時ui顯示的三種狀態
 * 分別爲加載中,加載失敗,無數據
 * email: [email protected]
 * @author qinwei create by 2015/10/28
 */
public class LoadingView extends FrameLayout implements OnClickListener {

    private View empty;
    private View error;
    private View loading;
    private State state;
    private OnRetryListener listener;

    public interface OnRetryListener {
        void onRetry();
    }

    public enum State {
        ing, error, done, empty
    }

    public LoadingView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        initializeView(context);
    }

    public LoadingView(Context context, AttributeSet attrs) {
        super(context, attrs);
        initializeView(context);
    }

    public LoadingView(Context context) {
        super(context);
        initializeView(context);
    }

    private void initializeView(Context context) {
        LayoutInflater.from(context).inflate(R.layout.widget_loading_view, this);
        empty = findViewById(R.id.empty);
        loading = findViewById(R.id.loading);
        error = findViewById(R.id.error);
        setOnClickListener(this);
        notifyDataChanged(State.ing);
    }

    public void notifyDataChanged(State state) {
        this.state = state;
        switch (state) {
            case ing:
                setVisibility(View.VISIBLE);
                loading.setVisibility(View.VISIBLE);
                empty.setVisibility(View.GONE);
                error.setVisibility(View.GONE);
                break;
            case empty:
                setVisibility(View.VISIBLE);
                loading.setVisibility(View.GONE);
                empty.setVisibility(View.VISIBLE);
                error.setVisibility(View.GONE);
                break;
            case error:
                setVisibility(View.VISIBLE);
                loading.setVisibility(View.GONE);
                empty.setVisibility(View.GONE);
                error.setVisibility(View.VISIBLE);
                break;
            case done:
                setVisibility(View.GONE);
                break;
            default:
                break;
        }
    }

    public void setOnRetryListener(OnRetryListener listener) {
        this.listener = listener;
    }
    public void setEmptyView(View view) {
        empty.removeAllViews();
        empty.addView(view);
    }
    @Override
    public void onClick(View v) {
        if (listener != null && state == State.error) {
            listener.onRetry();
        }
    }
}

widget_loading_view.xml佈局:

<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <LinearLayout
        android:id="@+id/empty"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center"
        android:orientation="vertical"
        android:visibility="gone">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="無數據" />
    </LinearLayout>

    <LinearLayout
        android:id="@+id/loading"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center"
        android:orientation="vertical">
        <!---mWidgetContainerView-->
        <ProgressBar
            android:id="@+id/progressBar"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />
    </LinearLayout>

    <LinearLayout
        android:id="@+id/error"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center"
        android:orientation="vertical"
        android:visibility="gone">

        <ImageView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@drawable/ic_load_err" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="8dp"
            android:text="網絡出問題啦"
            android:textColor="#8e9fa5"
            android:textSize="12sp" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="8dp"
            android:text="點擊屏幕,重新加載"
            android:textColor="#8e9fa5" />
    </LinearLayout>

</merge>

LoadingView如何使用呢
1.xml佈局引入LoadingView

<cn.wei.library.widget.LoadingView
 android:id="@+id/mLoadingView"
 android:layout_width="match_parent"
 android:layout_height="match_parent" />

2.activity或者fragment裏面

import android.view.Menu;
import android.view.MenuItem;
import android.widget.ViewSwitcher;

import cn.wei.library.widget.EmptyView;
import cn.wei.weilibrary.R;
import cn.wei.weilibrary.base.BaseTitleActivity;

public class EmptyViewActivity extends BaseActivity implements EmptyView.OnRetryListener {

    private ViewSwitcher mViewSwitcher;
    private EmptyView mEmptyView;

    @Override
    protected void setContentView() {
        setContentView(R.layout.activity_empty_view);
    }

    @Override
    protected void initializeData() {
        setTitle("EmptyView");
        mLoadingView= (LoadingView) findViewById(R.id.mEmptyView);
        mLoadingView.setOnRetryListener(this);
        mLoadingView.notifyDataChanged(LoadingView.State.ing);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.menu_emtyp_view, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case R.id.action_nodata:
                mLoadingView.notifyDataChanged(LoadingView.State.empty);
                break;
            case R.id.action_loading:
                mLoadingView.notifyDataChanged(LoadingView.State.ing);
                break;
            case R.id.action_err:
                mLoadingView.notifyDataChanged(LoadingView.State.error);
                break;
            default:
                break;
        }
        return super.onOptionsItemSelected(item);
    }

    @Override
    public void onRetry() {
        mLoadingView.notifyDataChanged(LoadingView.State.ing);
    }
}

嘿嘿還差個BaseActivity基類(關於在base類的講解,以後單獨出一篇文章解釋)給大家補上

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;

/**
 * 結構化activity的代碼
 * 方法調用順序爲setContentView()->initializeView()-> initializeData();
 */
public abstract class BaseActivity extends AppCompatActivity {
    protected String TAG = this.getClass().getSimpleName();

    @Override
    protected void onCreate(Bundle saveInstance) {
        super.onCreate(saveInstance);
        setContentView();
        initializeView();
        initializeData();
    }

    @Override
    protected void onStart() {
        super.onStart();
    }

    @Override
    protected void onResume() {
        super.onResume();
    }

    @Override
    protected void onPause() {
        super.onPause();
    }

    @Override
    protected void onStop() {
        super.onStop();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
    }

    /**
     * 1. 設置佈局
     */
    protected abstract void setContentView();

    /**
     * 2. 初始化佈局
     */
    protected abstract void initializeView();


    /**
     * 3. 初始化ui數據
     */
    protected abstract void initializeData();
}

是不是很簡單呢,https://github.com/qinweiforandroid/LoadingView

結束語

最近纔開始寫博客,如果文章裏有什麼不對的地方還請大家斧正!
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章