美文网首页
自定义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

    现在的app基本上都是从服务器获取数据 ,并把数据显示到页面上。我之前用的是dialog,但是dialog只有在加...

  • 如果使用nib创建自定义的view

    为了以后使用的时候方便,对于nib创建自定义view,我做了公用方法的抽取,以后再自定义的时候只需继承抽取出来的C...

  • Intellij 高阶快捷

    多行操作 自定义快捷输入 例如ps打出private string 需要先自定义``` 搜索 变量的抽取,comm...

  • RuiJi Scraper 选择器函数

    选择器函数用于用户调用自定义方法处理抽取结果,我们需要抽取的页面显示的抽取结果,有可能并不是我们想要的最终结果,这...

  • 自定义Subscriber

    /** * 自定义Subscriber,将dialog、complete、error、错误返回抽取出来,实现类中只...

  • react的一些总结

    什么时候自定义Hook? 当多个组件之间有一些公共的逻辑,可以将他们抽取成自定义的Hook,Hook本质是自定义的...

  • 自定义hook

    多个组件有相同的逻辑的时候,可以把他抽取到一个独立的hook里面。自定义hook的本质就是函数代码的抽取,他本身不...

  • 2

    结构 1:自定义组合控件,自定义属性 2:抽取样式 3:设置有跑马灯要过的文字或者图片 4:使用GridView

  • 自定义指令(中)

    简介 上一节讲了自定义指令的配置项,这一节我们看下自定义指令的作用域,自定义指令在开发中对于功能的抽取有着...

  • 设置导航控制器UIBarButtonItem的样式

    方法一:重复使用需要抽取代码 方法二:直接在自定义导航控制器设置

网友评论

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

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