在最近公布的比赛框架中,发现了页面加载管理类,觉得挺有用的,所以做个简单的笔记。

什么是页面加载管理类呢?(大佬可直接跳过翻看实现过程)

如果能有这个问题,那么很好,哈哈哈,你和我一样,刚开始都挺疑惑的。

我们一般在写网络请求的时候,如果不涉及什么MVP,或者别的,就一个简单网络请求,然后再成功的结果里刷新View,请求过程中总不能白屏吧,所以有些人可能会让转一个圈,或者显示加载中的布局,然后等成功后再隐藏掉,显示具体的布局view。这样的话,也没什么问题,但是如果你的状态需要多个,这个时候就很烦了。总不能每个状态的判断一下吧。再者说这样也不利于你解耦。

出于上面的需求,我们用下面的demo,来解决问题,先用一张图来看效果吧。

我们来具体看一下实现过程

/*** 页面加载管理类,根据不同的状态显示不同的view*/
public abstract class ContentPage extends FrameLayout{/**加载中的view*/private View loadingView;/**加载失败的view*/private View errorView;/**加载数据为空的view*/private View emptyView;/**加载成功的view*/private View successView;/**默认是加载中的状态*/private PageState mState = PageState.STATE_LOADING;/*** 定义页面状态常量**/public enum PageState{STATE_LOADING(0),/*加载中的状态*/STATE_SUCCESS(1),/*加载成功的状态*/STATE_ERROR(2),/*加载失败的状态*/STATE_EMPTY(3);/*加载数据为空的状态*/private int value;PageState(int value){this.value = value;}public int getValue(){return value;}}public ContentPage(Context context, AttributeSet attrs, int defStyle) {super(context, attrs, defStyle);initPage();}public ContentPage(Context context, AttributeSet attrs) {super(context, attrs);initPage();}public ContentPage(Context context) {super(context);initPage();}/*** 初始化Page*/private void initPage(){LayoutParams params = new LayoutParams(LayoutParams.MATCH_PARENT,LayoutParams.MATCH_PARENT);if(loadingView==null){/*天然往ContentPage中添加4个状态对应的view,然后根据不同状态,显示不同的view,添加LoadingView*/loadingView = View.inflate(getContext(), R.layout.page_loading, null);}addView(loadingView, params);if(errorView==null){/*添加ErrorView*/errorView = View.inflate(getContext(), R.layout.page_error, null);Button btn_reload = errorView.findViewById(R.id.btn_reload);btn_reload.setOnClickListener(v -> {mState = PageState.STATE_LOADING;showPage();loadDataAndRefreshPage();/*重新加载*/});}addView(errorView, params);if(emptyView==null){/*添加EmptyView*/emptyView = View.inflate(getContext(), R.layout.page_empty, null);}addView(emptyView, params);if(successView==null){/*添加SuccessView*/successView = createSuccessView();}if(successView==null){throw new IllegalArgumentException("The method createSuccessView() can not return null!");}else {addView(successView, params);}showPage();/*根据不同的state显示不同的view*/loadDataAndRefreshPage();/*请求数据然后刷新View*/}/*** 请求服务器的数据,然后根据加载的数据刷新View*/private void loadDataAndRefreshPage(){new Thread(){public void run() {Object result = loadData();/*获取加载完成的数据*/mState = checkData(result);/*根据数据判断当前page的状态*//*根据最新state,刷新View*/CommonUtil.runOnUIThread(() -> showPage());}}.start();}/*** 根据数据检查对应的状态* @return*/private PageState checkData(Object result){if(result!=null){if(result instanceof List){List list = (List) result;if(list.size()==0){return PageState.STATE_EMPTY;/*加载数据为空*/}else {return PageState.STATE_SUCCESS;/*加载成功*/}}else {return PageState.STATE_SUCCESS;/*加载成功*/}}else {return PageState.STATE_ERROR;/*加载失败*/}}public void refreshPage(Object o) {if (o == null) {//说明木有数据,那么对应的state应该是errormState = PageState.STATE_ERROR;} else {//说明请求回来的有数据,那么对应的state应该是successmState = PageState.STATE_SUCCESS;}showPage();}/*** 根据不同的state显示不同的view*/private void showPage(){loadingView.setVisibility(mState== PageState.STATE_LOADING?View.VISIBLE:View.INVISIBLE);errorView.setVisibility(mState== PageState.STATE_ERROR?View.VISIBLE:View.INVISIBLE);emptyView.setVisibility(mState== PageState.STATE_EMPTY?View.VISIBLE:View.INVISIBLE);successView.setVisibility(mState== PageState.STATE_SUCCESS?View.VISIBLE:View.INVISIBLE);}/*** 每个界面的成功view都不一样,应该由每个界面自己提供* @return*/public abstract View createSuccessView();/*** 由于每个界面加载数据的过程不一样,我只需要关心它加载回来之后的数据,然后根据数据刷新View* @return*/public abstract Object loadData();
}

现在看一下它的四种不同状态view

加载中 Loading...

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"><ProgressBarstyle="@android:style/Widget.ProgressBar"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity="center"android:indeterminateDrawable="@drawable/indeterminate_drawable" /></FrameLayout>

加载失败

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent" ><RelativeLayoutandroid:layout_width="match_parent"android:layout_height="match_parent"android:gravity="center" ><ImageViewandroid:id="@+id/page_iv"android:layout_width="100dp"android:layout_height="100dp"android:layout_centerHorizontal="true"android:scaleType="centerInside"android:src="@drawable/ic_error_page" /><Buttonandroid:id="@+id/btn_reload"android:layout_width="wrap_content"android:layout_height="34dp"android:layout_below="@id/page_iv"android:layout_centerHorizontal="true"android:layout_marginTop="10dp"android:background="@drawable/btn_bg"android:ellipsize="end"android:paddingLeft="10dp"android:paddingRight="10dp"android:singleLine="true"android:text="加载失败,点击重试"android:textColor="#ff717171"android:textSize="16sp" /></RelativeLayout></FrameLayout>

数据为null

<?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"android:layout_width="match_parent"android:layout_height="match_parent"><ImageViewandroid:id="@+id/image"app:layout_constraintBottom_toBottomOf="parent"app:layout_constraintRight_toRightOf="parent"app:layout_constraintTop_toTopOf="parent"app:layout_constraintLeft_toLeftOf="parent"android:layout_width="wrap_content"android:layout_height="wrap_content"android:src="@drawable/tree"android:contentDescription="@string/no_data" /><TextViewandroid:id="@+id/textView"android:layout_width="wrap_content"android:layout_height="wrap_content"android:textSize="20sp"android:text="@string/no_data"app:layout_constraintTop_toBottomOf="@id/image"app:layout_constraintLeft_toLeftOf="parent"app:layout_constraintRight_toRightOf="parent"/></android.support.constraint.ConstraintLayout>

加载成功

这个布局就不用写了,就是你自己要显示的布局

那么具体在代码中如何使用呢,我们看下面这个Demo。

先是一个BaseFragment的基类。

/*** @author Petterp* @date 2019/5/21.*/
public abstract class BaseFragment extends SupportFragment implements View.OnClickListener {public ContentPage contentPage;public ProgressDialog pdLoading;protected Activity mActivity;protected Context mContext;private Unbinder mUnBinder;@Overridepublic void onAttach(Context context) {mActivity = (Activity) context;mContext = context;super.onAttach(context);}@Nullable@Overridepublic View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {/** 初始化pdLoading*/pdLoading = new ProgressDialog(getActivity());pdLoading.setProgressStyle(ProgressDialog.STYLE_SPINNER);pdLoading.setMessage("请稍后");pdLoading.setCanceledOnTouchOutside(false);pdLoading.setCancelable(true);if (contentPage == null) {contentPage = new ContentPage(getActivity()) {@Overridepublic Object loadData() {return requestData();}@Overridepublic View createSuccessView() {return getSuccessView();}};} else {removeSelfFromParent(contentPage);}return contentPage;}@Overridepublic void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {super.onViewCreated(view, savedInstanceState);mUnBinder = ButterKnife.bind(this, view);}/*** 初始化 Toolbar*/protected void initToolBar(Toolbar toolbar, boolean homeAsUpEnabled, String title) {((BaseActivity) getActivity()).initToolBar(toolbar, homeAsUpEnabled, title);}/*** 刷新状态**/public void refreshPage(Object o) {contentPage.refreshPage(o);}/*** 返回据的fragment填充的具体View*/protected abstract View getSuccessView();/*** 返回请求服务器的数据*/protected abstract Object requestData();@Overridepublic void onDestroyView() {super.onDestroyView();mUnBinder.unbind();}public void removeSelfFromParent(View child) {// 获取父viewif (child != null) {ViewParent parent = child.getParent();if (parent instanceof ViewGroup) {ViewGroup viewGroup = (ViewGroup) parent;// 将自己移除viewGroup.removeView(child);}}}}

 然后是一个模拟Fragment


/*** 模拟Fragment*/
public class FirstFragment extends BaseFragment {@Overrideprotected View getSuccessView() {TextView textView = new TextView(getActivity());textView.setText("第一页");return textView;}@Overrideprotected Object requestData() {SystemClock.sleep(1000);/*模拟请求服务器的延时过程*/return "";/*加载成功*/}@Overridepublic void onClick(View view) {}/*** 类似于 Activity的 onNewIntent()*/@Overridepublic void onNewBundle(Bundle args) {super.onNewBundle(args);}
}

好啦,具体就是这样呢,相应的注释都挺详细的,如果有什么地方不对,也欢迎大家指出。

一个简单的页面加载管理类(包含加载中,加载失败,数据为空,加载成功)相关推荐

  1. 一个简单的PHP邮件列表管理器

    1.需求分析 管理员应该能够建立和修改邮件内容. 管理员应该能够将文本或HTML格式的新闻信件发送给一个列表中的所有订阅者. 用户应该能够通过注册使用一个站点,并且可以进入并修改他们的个人资料. 用户 ...

  2. 入门攻略丨教你用低代码实现一个简单的页面跳转功能

    一.介绍 HUAWEI DevEco Studio(后文简称:IDE)自2020年9月首次发布以来,经10次迭代升级,不断为HarmonyOS应用开发增强能力.3月31日,IDE再度升级到DevEco ...

  3. python自学篇十[ 面向对象 (四) :王者荣耀小游戏+模拟一个简单的银行进行业务办理的类]

    python基础系列: python自学篇一[ Anaconda3安装 ] python自学篇二[ pycharm安装及使用 ] python自学篇三[ 判断语句if的使用 ] python自学篇四[ ...

  4. JAVA程序设计(自主模式)-创建一个简单的表示矩形的Rectangle类

    创建一个简单的表示矩形的Rectangle类,满足以下条件: 1.定义两个成员变量height和width,表示矩形的长和宽,类型为整型 2.定义一个getArea方法,返回矩形的面积 3.定义一个g ...

  5. 计算机是否属于公共管理类,公共管理类包含的专业有哪些

    公共管理类包含的专业有:工商管理,旅游管理,社会保障,劳动与社会保障,劳动和社会保障,土地资源管理,海关管理,海事管理,海洋管理,边防管理等. 公共管理类研究生专业 管理科学与工程,行政管理,社会医学 ...

  6. 一串首尾相连的珠子(m个),有N种颜色(N《=10),设计一个算法,取出其中一段,要求包含所有N中颜色,并使长度最短。并分析时间复杂度与空间复杂度。

    一串首尾相连的珠子(m个),有N种颜色(N<=10),设计一个算法,取出其中一段,要求包含所有N中颜色,并使长度最短.并分析时间复杂度与空间复杂度. 这道题在网上著名的帖子 微软等公司数据结构+ ...

  7. idea 找不到或无法加载主类_解决IDEA中Groovy项目no Groovy library is defined的问题

    实验环境 IDEA2019.1.2 Groovy-2.5.8 错误重现 新建了一个Groovy工程,指定了groovy版本,如图 新建了一个简单的Groovy Class,运行,出现如下错误 错误的尝 ...

  8. 错误 找不到或无法加载主类mysql_解决Eclipse中“诡异”的错误:找不到或无法加载主类...

    记录下来遇到的(问题,解决方法),是更有效的解决问题的方式.(原谅我领悟的太晚与懒,从此用更有意义的方法,做一个更有意义的人) 因为遇到了多次,参考同一个方法,原文连接:https://blog.cs ...

  9. linux 页面内容输出,Node.js 一个简单的页面输出

    最近决定重拾node.js,用它来做一个合并JS文件的东西.由于忘得差不多了,先看能不能输出一个页面来再说.以下是我的一些笔记,省得以后又忘净光-- 安装过程就不说了.如果成功是能使用node的命令. ...

最新文章

  1. 安装凤凰os_这些系统帮助我们实现了在PC上安装安卓系统!
  2. css和JavaScript
  3. python详细教程-python入门(非常详细的教程)
  4. Java单例设计模式(实现Java的一个类只有一个对象)
  5. 格瑞光电:智慧城市建设的引领者
  6. 部署Small Business Server 2003服务器之一
  7. linux查代替命令,Linux下查/删/替 命令(转)
  8. linux last failed login表示什么意思_Linux用户
  9. python的底层实现,Python封装底层实现原理详解(通俗易懂)
  10. 给爱设计的你,一个理由爱上(和使用)渐变素材的理由
  11. python tkinter画笑脸_tkinter绘制红绿灯图案
  12. 【C#】CLR内存那点事(string)
  13. C#昵图素材下载器源码可下我图、包图、千图等(带数据库)
  14. 宏基ACER E1-471G拆机心得及注意事项
  15. Kindle fire 刷机
  16. QT操作word表格——垂直居中、水平居中
  17. 微信最新防封技术,域名防红技术分析
  18. O32 对接 交易所报盘软件_沈阳企业“新”社保报盘软件(下载地址)!
  19. 优麒麟mysql_如何在优麒麟Ubuntu Kylin下安装Numix主题和图标
  20. OMRON欧姆龙PLC如何实现远程上下载程序?

热门文章

  1. 加速度传感器灵敏度表示的几种方式LSB/g,count/g,V/g,V/°,请给出几种方式之间的说明及转换公式
  2. 信息技术与计算科学(二)信息的度量
  3. 华为鸿蒙新平板,华为鸿蒙Beta 3.0 版本推送更新 预装鸿蒙新平板获入网许可
  4. 我成功转型大厂数据分析师后,总结了这些经验…
  5. windows安装软件出现“command line option syntax error”错误
  6. 阿里智能化接口测试平台--暴雪
  7. 30用一个例子解释mapping到底是什么
  8. 噩梦的开始:动态规划之背包问题(01背包问题、完全背包问题、方案数填满型背包问题)
  9. 前端开发----简介
  10. 自动化测试框架[Cypress元素操作详解]