Android fragment 页面,[38→100]一个常规的Android页面模型:NetFragment

该博客探讨了Android开发中页面加载逻辑的处理,包括加载、空数据、异常和错误界面的显示。通过约定优于配置的原则,定义了特定的id来标识不同界面,并遵循单一责任原则,将界面显示与数据加载分离。NetFragment类负责网络数据的加载和界面控制,而各个界面的交互由各自处理。此外,提出了内置子类以实现常见场景的快速集成,如加载框、刷新加载、错误提示等。
摘要由CSDN通过智能技术生成

问题场景

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值