Android fragment 页面,[38→100]一个常规的Android页面模型:NetFragment
问题场景
Android开发中大部分页面都包含如下逻辑:
进入页面,加载网络数据,显示加载页面
加载完成后,有以下几种情况:
正常返回,有有效数据,显示“有效界面”
正常返回,有效数据为空,显示“空数据界面”
正常返回,服务器判定输入参数异常,显示“参数异常界面”,比如“用户登录失效”等,直接跳转相应的页面
异常返回,网络超时,无法访问服务器等状态,显示“加载失败页面”
无法访问网络,显示“无法访问网络界面”。
怎么解决呢?
原本想各个界面由NetFragment提供接口进行设置,后来考虑Android的界面基本xml绘制,透过id与代码绑定。那不如采用“约定优于配置原则”,直接规定好那些id标识哪些界面,NetFragment里面根据相应的id去寻找界面即可。所以最后约定id名称如下:
加载界面 R.id.net_progress
有效界面 R.id.net_result
空数据界面 R.id.net_no_result
参数异常界面 R.id.net_error
加载失败页面 R.id.net_fail
无法访问网络界面 R.id.net_cannot_access
基于SOLID原则中的S——单一责任原则(The Single Responsibility Principle),各个界面的点击、触摸都由各自处理,NetFragment只负责加载数据、控制各类界面显示隐藏,至于下拉刷新、上拉加载下一页数据等操作都不在此类里面内进行管理。
最后产生的代码——NetFragment.java
package lib;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.freetek.deepsea.R;
import panda.android.lib.base.control.SimpleSafeTask;
import panda.android.lib.base.model.ListNetResultInfo;
import panda.android.lib.base.model.NetResultInfo;
import panda.android.lib.base.model.net.BaseRepositoryCollection;
import panda.android.lib.base.ui.fragment.BaseFragment;
import panda.android.lib.base.util.DevUtil;
import panda.android.lib.base.util.Log;
/**
* 加载网页数据的通用模型,包含 进度条控制、结果显示控制。
*
* @param
* @author shitianci
*/
public abstract class NetFragment extends BaseFragment {
private static final String TAG = NetFragment.class.getSimpleName();
protected View mViewProgress = null; //加载界面
protected View mViewResult = null; //有效界面
protected View mViewNoResult = null; //空数据界面
protected View mViewError = null; //参数异常界面
protected View mViewFail = null; //加载失败页面
protected View mViewCannotAccess = null; //无法访问网络
protected SimpleSafeTask netTask = null;
private View[] mViewArray;
private int[] mViewArrayID = new int[]{
R.id.net_progress, //加载界面
R.id.net_result, //有效界面
R.id.net_no_result, //空数据界面
R.id.net_error, //参数异常界面
R.id.net_fail, //加载失败页面
R.id.net_cannot_access}; //无法访问网络
//todo 这些数据需要放到xml里面进行管理
private String[] mViewToastString = new String[]{
"正在加载中", //加载界面
"加载到有效数据了", //有效界面
"加载数据为空", //空数据界面
"参数异常", //参数异常界面
"无法访问服务器", //加载失败页面
"无法访问网络"}; //无法访问网络
@Override
public int getLayoutId() {
return R.layout.panda_fragment_net;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View createdView = super.onCreateView(inflater, container,
savedInstanceState);
mViewProgress = createdView.findViewById(R.id.net_progress);
mViewResult = createdView.findViewById(R.id.net_result);
mViewNoResult = createdView.findViewById(R.id.net_no_result);
mViewError = createdView.findViewById(R.id.net_error);
mViewFail = createdView.findViewById(R.id.net_fail);
mViewCannotAccess = createdView.findViewById(R.id.net_cannot_access);
mViewArray = new View[]{mViewProgress, mViewResult, mViewNoResult, mViewError, mViewFail, mViewCannotAccess};
return createdView;
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
loadNetData(false);
}
boolean loadingNetData = false;
public void loadNetData() {
loadNetData(false);
}
public void loadNetData(final boolean useSecondModel) {
Log.d(TAG, "loadNetData, loadingNetData = " + loadingNetData);
if (loadingNetData) {
return;
}
if (!BaseRepositoryCollection.tryToDetectNetwork(getActivity())) {
showOnlyView(R.id.net_cannot_access, useSecondModel);
return;
}
netTask = new SimpleSafeTask(getActivity()) {
protected void onPreExecuteSafely() throws Exception {
loadingNetData = true;
showOnlyView(R.id.net_progress, useSecondModel);
onPreloadNetData(useSecondModel);
}
@Override
protected T doInBackgroundSafely() throws Exception {
T result = onDoInBackgroundSafely();
return result;
}
@Override
protected void onPostExecuteSafely(T result, Exception e) {
onPostloadNetData(useSecondModel);
super.onPostExecuteSafely(result, e);
loadingNetData = false;
if (e != null || result == null) {
showOnlyView(R.id.net_fail, useSecondModel);
return;
}
if (result.getRespCode() != NetResultInfo.RETURN_CODE_000000) {
showOnlyView(R.id.net_error, useSecondModel);
return;
}
if (result instanceof ListNetResultInfo && ((ListNetResultInfo) result).getList().size() == 0) {
showOnlyView(R.id.net_no_result, useSecondModel);
return;
}
showOnlyView(R.id.net_result, useSecondModel);
onDisplayResult(result);
}
protected void onCancelled() {
loadingNetData = false;
showOnlyView(R.id.net_fail, useSecondModel);
}
};
netTask.execute();
return;
}
/**
* -------------------------
* START: 最重要的流程方法
* -------------------------
*/
/**
* 开始加载网络数据
* @param useSecondModel
*/
public void onPreloadNetData(boolean useSecondModel) {
}
/**
* 加载后台数据
*
* @return
*/
protected abstract T onDoInBackgroundSafely();
/**
* 显示后台数据
*
* @param result
*/
protected abstract void onDisplayResult(T result);
/**
* 网络数据加载结束
* @param useSecondModel
*/
public void onPostloadNetData(boolean useSecondModel) {
}
/**
* -------------------------
* END
* -------------------------
*/
/**
* -------------------------
* START: 纯粹的界面展示控制,不推荐外部调用、重写
* -------------------------
*/
/**
* 显示指定的View,剩下的界面都隐藏。
*
* @param useSecondModel 是否启用第二次模式,在加载第2……n次数据时,无需切换其它界面,采用Toast显示信息即可。
*/
protected void showOnlyView(int viewId, boolean useSecondModel) {
int i = 0;
for (View v : mViewArray) {
i++;
if (v == null) {
continue;
} else if (v.getId() == viewId) {
Log.d(TAG, "showOnlyView, i = " + i);
if (useSecondModel && (viewId != R.id.net_progress || viewId != R.id.net_result)) {
DevUtil.showInfo(getActivity(), mViewToastString[i-1]);
} else {
v.setVisibility(View.VISIBLE);
}
} else {
v.setVisibility(View.GONE);
}
}
}
protected void showProgress() {
Log.d(TAG, "showProgress, mViewProgress = " + mViewProgress);
if (mViewProgress != null) {
mViewProgress.setVisibility(View.VISIBLE);
}
}
protected void hiddenProgress() {
Log.d(TAG, "hiddenProgress, mViewProgress = " + mViewProgress);
if (mViewProgress != null) {
mViewProgress.setVisibility(View.GONE);
}
}
// protected void showResult() {
// Log.d(TAG, "showResult");
// if (mViewResult != null) {
// mViewResult.setVisibility(View.VISIBLE);
// }
// }
//
// protected void hiddenResult() {
// Log.d(TAG, "hiddenResult");
// if (mViewResult != null) {
// mViewResult.setVisibility(View.GONE);
// }
// }
//
// protected void showNoResult() {
// Log.d(TAG, "showNoResult");
// if (mViewNoResult != null) {
// mViewNoResult.setVisibility(View.VISIBLE);
// }
// }
//
// protected void hiddenNoResult() {
// Log.d(TAG, "hiddenNoResult");
// if (mViewNoResult != null) {
// mViewNoResult.setVisibility(View.GONE);
// }
// }
//
// public void showError() {
// Log.d(TAG, "showNetErrResult");
// if (mViewError != null) {
// mViewError.setVisibility(View.VISIBLE);
// }
// }
//
// private void hiddenError() {
// if (mViewError != null) {
// mViewError.setVisibility(View.GONE);
// }
// }
//
// public void showFail() {
// Log.d(TAG, "showFail");
// if (mViewFail != null) {
// mViewFail.setVisibility(View.VISIBLE);
// }
// }
//
// public void hiddenFail() {
// Log.d(TAG, "hiddenFail");
// if (mViewFail != null) {
// mViewFail.setVisibility(View.GONE);
// }
// }
//
// public void showCannotAccess() {
// if (mViewCannotAccess != null) {
// mViewCannotAccess.setVisibility(View.VISIBLE);
// }
// }
//
// public void hiddenCannotAccess() {
// if (mViewCannotAccess != null) {
// mViewCannotAccess.setVisibility(View.GONE);
// }
// }
/**
* -------------------------
* END
* -------------------------
*/
}
后续拓展
可以从开发者使用角度考虑,内置一系列子类,达到各种场景中“One Step”集成的效果。比如默认效果为:
加载界面:弹出一个透明背景的加载框
有效界面:支持 下拉刷新、上拉加载下一页
空数据界面:支持图文格式
参数异常界面:采用Toast提示
加载失败页面:提醒用户网速过慢,建议切换网络
无法访问网络界面:提醒用户打开网络
Panda
2016-06-03
Android fragment 页面,[38→100]一个常规的Android页面模型:NetFragment相关推荐
- android log耗性能吗,一个高性能的Android日志库
clue 一个高性能的Android日志库. 为什么性能高 通常的Android日志库, 为了获取到class名, 方法名, 行号, 都是通过以下API实现的: StackTraceElement[] ...
- Android fragment 中控制某一个界面全屏与否
项目中,只允许一个界面在横屏的时候,显示是全屏的,竖屏切换回来的时候又需要显示状态栏,所以需要监听横竖屏的状态,还要修改状态栏的隐藏与显示,如下代码: /*** 添加横竖屏监听,隐藏图形的菜单控件,2 ...
- android fragment相机,简单的易于集成的Android相机Fragment – Camer...
CameraFragment 一个简单的易于集成的Android相机Fragment. //you can configure the fragment by the configuration bu ...
- android视频播放器ui,ArtVideoPlayer 一个灵活的Android视频播放器,支持全屏,小屏播放...
ArtPlayer 简介 Kotlin实现的视频播放器,将MediaPlayer与VideoView解耦合,支持切换播放器内核(如ExoPlayer和ijkPlayer),支持自定义控制视图,提供Me ...
- html js注册页面代码,JS一个简单的注册页面实例
// $(function(){ // $("input[name='uname']").blur(function(){ // var unamestr = $(this).va ...
- XRouter 一个轻量级的Android路由框架,基于ARouter上进行改良,优化Fragment的使用,可结合XPage使用
XRouter 一个轻量级的Android路由框架,基于ARouter上进行改良,优化Fragment的使用,可结合XPage使用. 关于我 特征 由于是借鉴了ARouter,拥有ARouer所有特征 ...
- xpage 传参_一个轻量级的Android路由框架,基于ARouter上进行改良,优化Fragment的使用,可结合XPage使用。...
XRouter 一个轻量级的Android路由框架,基于ARouter上进行改良,优化Fragment的使用,可结合XPage使用. 关于我 特征 由于是借鉴了ARouter,拥有ARouer所有特征 ...
- android开发 转跳功能,如何在Android中利用Intent实现一个页面跳转功能
如何在Android中利用Intent实现一个页面跳转功能 发布时间:2021-02-20 17:06:31 来源:亿速云 阅读:113 作者:Leah 本篇文章为大家展示了如何在Android中利用 ...
- Android Fragment 真正彻底的解决(下一个)
转载请注明出处:http://blog.csdn.net/lmj623565791/article/details/37992017 上篇博客中已经介绍了Fragment产生原因.以及一些主要的使用方 ...
最新文章
- SIGSEGV 和 SIGBUS gdb看汇编
- 【Android 热修复】运行 Tinker 官方示例 ( 处理 TINKER_ID 问题 | 编译 debug 包 | 修改 Gradle 脚本 | 生成 patch 包 | 热修复 )
- 最新代理服务器列表 2008-09-2
- 图神经网络三剑客:GCN、GAT与GraphSAGE
- 算法学习--Day5
- eclipse 使用 maven 无法编译 jsp 文件的问题
- C# —— IEnumerable和状态机
- sphereface 训练出现的问题
- 使用 jQuery Mobile 和 CSS3 实现响应式设计
- python—csv模块处理单字符分隔符文件
- 统计学习方法读书笔记8-朴素贝叶斯
- java 删除n天前的文件_linux自动删除n天前备份
- wps中的word删除空白页
- java二叉树详解_最全二叉树:完整详解二叉树的遍历以及完全二叉树等6种二叉树...
- 倾角传感器和陀螺仪传感器的区别
- android gps 方位角,GPS坐标系中的方位角计算
- 什么是视频编码 编解码技术及压缩技术
- slt mysql_SAP SLT操作手册 PDF 下载
- 跳过休息日(周末和节假日)
- Linux常用基础命令(巨全)你想要的我都有❀
热门文章
- 64位系统使用Access 数据库文件的彻底解决方法
- Android中数据库的一些操作(增删改查)
- 基础拾遗------泛型详解
- oracle pl/sql编程详细,Oracle框架:PL/SQL编程:
- excel匹配_Excel中的数据匹配和查找
- mac使用被动ftp模式(pasv)_ftp主动模式和被动模式
- centos7开启tcp6_Centos7下配置IPV6
- iview的表格自定义_Vue中使用iview-UI表格样式修改和使用自定义模板数据渲染相关...
- tableau linux无网络安装_举个栗子!Tableau 技巧(127):购物篮分析之关联购买
- Android开发之非常好用的日志工具类(公司项目挖出来的)