美文网首页
自定义LoadingPage并抽取LoadingBaseActi

自定义LoadingPage并抽取LoadingBaseActi

作者: 爱码士 | 来源:发表于2017-07-11 16:46 被阅读51次

    现在的app基本上都是从服务器获取数据 ,并把数据显示到页面上。我之前用的是dialog,但是dialog只有在加载数据的时候显示,并没有对加载数据结果进行处理(比如说加载失败出现提示并点击再次进行请求等)这样的效率并不是很高,为此抽取出了一个LoadingPage配合LoadingBaseActivity和BaseFragment使用大大增加了开发效率。

    这里定义了5种状态和对应状态显示的view,对外暴露了3个方法:

    • 方法1、getLayoutId() 获取数据加载成功后显示的布局id,一般就是XxxActivitiy和XxxFragment的布局
    • 方法2、initView() 子类关于View的操作(如ButterKnife的初始化,可以参考LoadingBaseActivity)都必须在这里面
    • 方法3、loadData() 当网络获取失败 点击进行网络请求时调用,根据网络获取的数据返回状态,每一个子类的获取网络返回的都不一样,所以要交给子类去完成。

    这里就以逗萌吧的例子展示下。说了那么多,直接贴代码看得更清晰。至于怎么使用可以参考LoadingBaseActivity和BaseFragment。

    public abstract class LoadingPage extends FrameLayout {
        public static final int STATE_UNKNOWN = 0;
        public static final int STATE_LOADING = 1;
        public static final int STATE_ERROR = 2;
        public static final int STATE_EMPTY = 3;
        public static final int STATE_SUCCESS = 4;
        private View loadingView;                 // 加载中的界面
        private View errorView;                   // 错误界面
        private View emptyView;                   // 空界面
        public  View contentView;                 // 加载成功的界面
    
        private AnimationDrawable mAnimationDrawable;//imageview的动画
        private ImageView img;//加载时显示的imageview
    
        public int state = STATE_UNKNOWN;
    
        private Context mContext;
       public LoadingPage(Context context) {
            this(context,null);
        }
    
        public LoadingPage(Context context, AttributeSet attrs) {
            this(context, attrs,0);
        }
    
        public LoadingPage(Context context, AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
            mContext = context;
            init();//初始化4种界面
        }
    
    
        private void init() {
            this.setBackgroundColor(getResources().getColor(R.color.colorPageBg));
            //把loadingView添加到frameLayout上
            if (loadingView == null) {
                loadingView = createLoadingView();
                this.addView(loadingView, LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
            }
            //把emptyView添加到frameLayout上
            if (emptyView == null) {
                emptyView = createEmptyView();
                this.addView(emptyView, LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
    
            }
            //把errorView添加到frameLayout上
            if (errorView == null) {
                errorView = createErrorView();
                this.addView(errorView, LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
            }
            showPage();//根据状态显示界面
        }
    
    
        private View createLoadingView() {
            loadingView = LayoutInflater.from(mContext).inflate(R.layout.loadingpage_state_loading, null);
            img = (ImageView) loadingView.getRootView().findViewById(R.id.img_progress);
            // 加载动画 这边也可以直接用progressbar
            mAnimationDrawable = (AnimationDrawable) img.getDrawable();
            // 默认进入页面就开启动画
            if (!mAnimationDrawable.isRunning()) {
                mAnimationDrawable.start();
            }
            return loadingView;
        }
    
        private View createEmptyView() {
            emptyView = LayoutInflater.from(mContext).inflate(R.layout.loadingpage_state_empty, null);
            return emptyView;
        }
    
        private View createErrorView() {
            errorView = LayoutInflater.from(mContext).inflate(R.layout.loadingpage_state_error, null);
            errorView.setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(View view) {
                    state = STATE_LOADING;
                    showPage();
                    loadData();
                }
            });
            return errorView;
        }
    
        private void startAnimation() {
            if (!mAnimationDrawable.isRunning()) {
                mAnimationDrawable.start();
            }
        }
    
        private void stopAnimation() {
            if (mAnimationDrawable != null && mAnimationDrawable.isRunning()) {
                mAnimationDrawable.stop();
            }
        }
    
        public void showPage() {
            if (loadingView != null) {
                if (state == STATE_UNKNOWN || state == STATE_LOADING) {
                    loadingView.setVisibility(View.VISIBLE);
                    // 开始动画
                    startAnimation();
                } else {
                    // 关闭动画
                    stopAnimation();
                    loadingView.setVisibility(View.GONE);
                }
            }
            if (state == STATE_EMPTY || state == STATE_ERROR || state == STATE_SUCCESS) {
                // 关闭动画
                stopAnimation();
            }
    
    
            if (emptyView != null) {
                emptyView.setVisibility(state == STATE_EMPTY ? View.VISIBLE : View.GONE);
            }
    
            if (errorView != null) {
                errorView.setVisibility(state == STATE_ERROR ? View.VISIBLE : View.GONE);
            }
    
            if (state == STATE_SUCCESS) {
                if (contentView == null) {
                    contentView = LayoutInflater.from(mContext).inflate(getLayoutId(), null);
                    addView(contentView, LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
                    initView();
                }
                contentView.setVisibility(View.VISIBLE);
            } else {
                if (contentView != null) {
                    contentView.setVisibility(View.GONE);
                }
            }
        }
    
       /**
         * 1、
         * @Description 初始化布局,当网络请求成功时显示
         */
        protected abstract int getLayoutId();
    
        /**
         * 2、
         * @Description 子类关于View的操作(如setAdapter)都必须在这里面,会因为页面状态不为成功,而binding还没创建就引用而导致空指针。
         */
        protected abstract void initView();
    
        /**
         * 3、
         * @Description 当网络获取失败 点击进行网络请求时调用
         * 根据网络获取的数据返回状态,每一个子类的获取网络返回的都不一样,所以要交给子类去完成
         */
        protected abstract void loadData();
    }
    

    项目地址 https://github.com/BingoKingCoding/MVPLearn

    相关文章

      网友评论

          本文标题:自定义LoadingPage并抽取LoadingBaseActi

          本文链接:https://www.haomeiwen.com/subject/lremhxtx.html