我们在开发中,网络请求经常会遇到各种错误码的判断。比如下面这样:
先不说正常的错误码,就项目中的这些码,不可能我们每次都自己去判一遍吧,这样也太麻烦了。刚好实习期间项目中有很多需要的地方,于是写了个简单的小工具。
代码很简单,并没有太多优化,我们在使用时可以按照自己的想法,自由定制,再多的设计模式都只是为了更好的使用,所以不用太过在意,如果考虑优化,那么可以进行更好的封装改造,这里我只是简单给一个解决的思想。
流程大概是这样的:
- 首先,创建自己的数据Bean类,GsonGormat一键生成,然后继承于BaseDataBean,利用泛型自由实现我们需求。成功返回我们需要的bean对象,否则弹出失败dialog。
- 使用时
String json="";
//请求成功与否:
boolean mode = ErrorDialogFragmentUtils
.Builder()
.setContext(getContext())
.setMessage("成功响应") //报错时将直接赋予错误码
.setManager(getFragmentManager())
.setIlistener(new IDialogListener() {
@Override
public void onPositiveClick() {
//确定按钮
}
@Override
public void onNegativeClick() {
//取消按钮
}
})
.setDialogDimss(() -> {
//dialog关闭监听
})
.setiDataCode((code, res) -> {
//接收网络码
})
.build()
.setJson(json, GLoginBean.class, gLoginBean -> {
//如果成功,这里拿到你的bean对象
});
3. 自由更改 ErrorDialogFragmentUtils 中的代码,比如错误码及一些特定错误码的处理逻辑。在这里,因为我们后端并没有对有些特定码有处理逻辑,所以我暂时空着,但为了备用,留下了错误码的出口,可以调用 setIDataCode(),实现相应的接口即可拿到失败码,更多的特定业务方法,可以仿照我的写法自由添加或者更改。
这里对一些处理逻辑,谈谈我的看法:
- 错误码存储采用 SpaseArray(性能更好),而非HashMap(内部枚举key),放在静态代码块,防止多次添加。具体根据个人业务需求。(如果需要自定义错误码提示,这个时候存储就起作用了,在 setJson 方法里面,自己加switch来决定)
- 为什么使用静态内部类,数据持有,同时避免访问外部变量或者方法,仿建造者的使用方式。(可以将Builder方法注释,然后采用 new ErrorDialogFragmentUtils.Client,然后也是一顿顿点点点,不过为了更习惯的使用,加入了Builder方法)
- DialogFragment 这个没得说,随便定义吧,这里我给出一个简单的提示窗口,大家可以随意发挥.
看一下代码,就很简单吧,下面开始上代码:
工具类,自由定义
代码语言:javascript复制/**
* Created by Petterp
* on 2019-09-24
* Function: 判断状态码,来做出不同处理。
*/
public class ErrorDialogFragmentUtils {
// private static SparseArray<String> codes;
/*static {
// 自定义相应的错误码,或者后端提供的话,忽略这里即可
codes = new SparseArray<>();
codes.put(-1, "系统繁忙,稍后重试");
codes.put(0, "操作成功");
codes.put(100, "验签错误,操作失败");
codes.put(200, "参数错误,操作失败");
codes.put(210, "用户名与密码不匹配,请重试");
codes.put(211, "登录验证码错误,请重试");
codes.put(900, "token失效,及时刷新");
codes.put(901, "token失效,重新登录");
codes.put(500, "逻辑异常");
}*/
private static class ClientParams {
private FragmentManager manager;
private Context context;
//是否显示自定义Message
private boolean isDiaMode = false;
//自定义Message
private String message = "";
//Dialog按钮监听
private IDialogListener ilistener;
//是否需要控制dialog关闭时操作
private IDataDialogDimss dialogDimss;
//返回网络码
private IDataCode iDataCode;
}
private ErrorDialogFragmentUtils() {
}
private ClientParams params;
private ErrorDialogFragmentUtils setParams(ClientParams params) {
this.params = params;
return this;
}
public static Client Builder() {
return new Client();
}
public static class Client {
private ClientParams params;
private Client() {
params = new ClientParams();
}
public Client setManager(FragmentManager manager) {
params.manager = manager;
return this;
}
public Client setContext(Context context) {
params.context = context;
return this;
}
public Client setMessage(String message) {
params.message = message;
params.isDiaMode = true;
return this;
}
public Client setDialogDimss(IDataDialogDimss dialogDimss) {
params.dialogDimss = dialogDimss;
return this;
}
public Client setIlistener(IDialogListener ilistener) {
params.ilistener = ilistener;
return this;
}
public Client setiDataCode(IDataCode iDataCode) {
params.iDataCode = iDataCode;
return this;
}
public ErrorDialogFragmentUtils build() {
return getUtils().setParams(params);
}
protected ErrorDialogFragmentUtils getUtils() {
return new ErrorDialogFragmentUtils();
}
}
/**
* 设置数据源并进行初步解析
*
* @param json
* @param g
* @param dataInfo
* @param <T>
* @return
*/
public <T extends BaseDataBean> boolean setJson(String json, Class<T> g, IDataSuccess<T> dataInfo) {
JSONObject jsonObject = JSONObject.parseObject(json);
JSONObject jsonObject1 = JSONObject.parseObject(jsonObject.getString("result"));
int code = jsonObject1.getInteger("c");
String res = jsonObject1.getString("m");
LatteLogger.e("demo", "数据解析器开始验证数据,code:" code "tres:" res "n数据源:" json);
//返回网络码
if (params.iDataCode != null) {
params.iDataCode.code(code, res);
}
//回调成功bean
if (code == 0) {
Gson gson = new Gson();
T bean = gson.fromJson(json, g);
dataInfo.getData(bean);
//如果用户需要显示成功Dialog,自定义显示
if (params.isDiaMode) {
ToastUtils.showText("成功");
showDialog(false);
} else {
params = null;
}
return true;
}
//以下为自定义业务处理
//优先报错业务处理
params.message = res;
if (code == 901) {
//token失效
showDialog(true);
} else {
//执行默认操作
showDialog(false);
}
return false;
}
private void showDialog(boolean mode) {
LatteLoader.stopLoading();
new CommonDialog
.Builder()
.setDialogDimss(() -> {
//以下逻辑根据业务需求去定
if (mode) {
//默认处理错误逻辑
restLogin();
}
if (params.dialogDimss != null) {
params.dialogDimss.onDialogDimss();
}
//清除配置信息
params = null;
})
.setContentMessage(params.message)
.setDialogButtonClickListener(new CommonDialog.OnDialogButtonClickListener() {
@Override
public void onPositiveClick(View v, Bundle bundle) {
if (params.ilistener != null) {
params.ilistener.onPositiveClick();
}
}
@Override
public void onNegativeClick(View v, Bundle bundle) {
if (params.ilistener != null) {
params.ilistener.onNegativeClick();
}
}
})
.build()
.show(params.manager, getClass().getName());
}
/**
* 自定义业务需要
*/
private void restLogin() {
。。。
}
}
Gson数据类
代码语言:javascript复制/**
* Created by Petterp
* on 2019-10-04
* Function: 统一Gson数据
*/
public class BaseDataBean {
}
代码语言:javascript复制public class GLoginBean extends BaseDataBean{
private ResultBean result;
private DataBean data;
private long refreshTime;
public ResultBean getResult() {
return result;
}
public void setResult(ResultBean result) {
this.result = result;
}
public DataBean getData() {
return data;
}
public void setData(DataBean data) {
this.data = data;
}
public long getRefreshTime() {
return refreshTime;
}
public void setRefreshTime(long refreshTime) {
this.refreshTime = refreshTime;
}
public static class ResultBean {
/**
* c : 0
* m : 操作成功
*/
private int c;
private String m;
public int getC() {
return c;
}
public void setC(int c) {
this.c = c;
}
public String getM() {
return m;
}
public void setM(String m) {
this.m = m;
}
}
public static class DataBean {
...
}
}
一个通用的DialogFragment对话框
代码语言:javascript复制/**
* 通用对话框
*/
public class CommonDialog extends DialogFragment {
private static class ControllerParams {
public boolean isCancelable;
public CharSequence contentMessage;
public Bundle expandParams;
public OnDialogButtonClickListener listener;
public int positiveText;
public int negativeText;
public OnDialogDimss dialogDimss;
private boolean isOnlyConfirm;
}
private static final String COMMON_DIALOG_PARAMS = "common_dialog_params";
private ControllerParams params;
@Override
public void onStart() {
super.onStart();
//透明化背景
Window window = getDialog().getWindow();
//背景色
window.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View view = getDialogView();
if (view == null) {
view = View.inflate(getContext(), R.layout.commom_dialog_base, null);
}
Button negative = view.findViewById(R.id.dialog_btn_negative);
Button positive = view.findViewById(R.id.dialog_btn_positive);
View btnSeparate = view.findViewById(R.id.dialog_v_btn_separate);
RelativeLayout contentContainer = view.findViewById(R.id.dialog_content_container);
TextView content = view.findViewById(R.id.dialog_tv_content);
negative.setOnClickListener(v -> {
dismiss();
if (onNegativeClick()) {
return;
}
if (params.listener != null) {
params.listener.onNegativeClick(v, getNegativeDatas());
}
});
positive.setOnClickListener(v -> {
dismiss();
if (onPositiveClick()) {
return;
}
if (params.listener != null) {
params.listener.onPositiveClick(v, getPositiveDatas());
}
});
if (params != null) {
View contentView = onCreateContentView();
if (contentView != null) {
contentContainer.removeAllViews();
contentContainer.addView(contentView);
} else if (!TextUtils.isEmpty(params.contentMessage)) {
content.setText(Html.fromHtml(params.contentMessage.toString()));
}
if (params.positiveText > 0) {
positive.setText(params.positiveText);
}
if (params.negativeText > 0) {
negative.setText(params.negativeText);
}
if (params.isOnlyConfirm) {
negative.setVisibility(View.GONE);
btnSeparate.setVisibility(View.GONE);
positive.setBackgroundResource(R.drawable.common_dialog_single_positive_seletor);
}
setCancelable(params.isCancelable);
}
Dialog dialog = getDialog();
if (dialog != null) {
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
}
return view;
}
/**
* 此方法只提供给布局改变, 但是控件id 不变的自定义 dialog 使用
*
* @return
*/
protected View getDialogView() {
return null;
}
/**
* 通过复写此方法, 在子类中,可重新创建设置
* 新的内容布局
*
* @return
*/
protected View onCreateContentView() {
return null;
}
/**
* 复写此方法, 并可在此方法中设置,回调监听确定按钮所需的数据
*
* @return
*/
protected Bundle getPositiveDatas() {
return null;
}
/**
* 复写此方法, 并可在此方法中设置,回调监听取消按钮所需的数据
*
* @return
*/
protected Bundle getNegativeDatas() {
return null;
}
/**
* 集成的子类假如想在内部处理 Positive 点击监听, 可复写此方法。 返回 true 则可拦截,不会走外部设置的点击监听
*
* @return true 拦截监听, false 不拦截
*/
protected boolean onPositiveClick() {
return false;
}
/**
* 集成的子类假如想在内部处理 Negative 点击监听, 可复写此方法。 返回 true 则可拦截,不会走外部设置的点击监听
*
* @return
*/
protected boolean onNegativeClick() {
return false;
}
private void setParams(ControllerParams params) {
this.params = params;
}
public Bundle getExpandParams() {
if (params == null) {
return null;
}
return params.expandParams;
}
public interface OnDialogButtonClickListener {
void onPositiveClick(View v, Bundle bundle);
void onNegativeClick(View v, Bundle bundle);
}
public interface OnDialogDimss {
void onCancel();
}
/**
* 集成 CommonDialog 的子类, 需要继承此类, 并要复写
* getCurrentDialog 方法,返回子类的dialog 对象
*/
public static class Builder {
private ControllerParams params;
public Builder() {
params = new ControllerParams();
}
public Builder setContentMessage(CharSequence content) {
params.contentMessage = content;
return this;
}
public Builder isCancelable(boolean cancelable) {
params.isCancelable = cancelable;
return this;
}
public Builder setButtonText(int positiveText, int negativeText) {
params.positiveText = positiveText;
params.negativeText = negativeText;
return this;
}
public Builder setDialogButtonClickListener(OnDialogButtonClickListener listener) {
params.listener = listener;
return this;
}
public Builder setExpandParams(Bundle expandParams) {
params.expandParams = expandParams;
return this;
}
/**
* 是否隐藏按钮
*
* @param isOnlyConfirm
* @return
*/
public Builder setIsOnlyConfirm(boolean isOnlyConfirm) {
params.isOnlyConfirm = isOnlyConfirm;
return this;
}
public Builder setDialogDimss(OnDialogDimss dialogDimss) {
params.dialogDimss = dialogDimss;
return this;
}
public CommonDialog build() {
CommonDialog dialog = getCurrentDialog();
dialog.setParams(params);
return dialog;
}
protected CommonDialog getCurrentDialog() {
return new CommonDialog();
}
}
@Override
public void onDismiss(@NonNull DialogInterface dialog) {
super.onDismiss(dialog);
if (params.dialogDimss!=null){
params.dialogDimss.onCancel();
}
}
}
dialog xml
代码语言:javascript复制<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="@dimen/common_dialog_width"
android:layout_height="wrap_content"
android:background="@drawable/common_dialog_bg"
android:paddingBottom="5dp"
android:orientation="vertical">
<RelativeLayout
android:id="@ id/dialog_content_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:minHeight="@dimen/common_dialog_common_min_height"
android:orientation="vertical">
<TextView
android:id="@ id/dialog_tv_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:paddingLeft="@dimen/common_dialog_text_margin_left"
android:paddingTop="@dimen/common_dialog_text_margin_top"
android:paddingRight="@dimen/common_dialog_text_margin_right"
android:paddingBottom="@dimen/common_dialog_text_margin_bottom"
android:textColor="@color/common_dialog_base_text"
android:textSize="@dimen/common_dialog_text_size" />
</RelativeLayout>
<View
android:layout_width="match_parent"
android:layout_height="@dimen/common_dialog_line_width"
android:background="@color/common_dialog_base_line" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="@dimen/common_dialog_button_height"
android:orientation="horizontal">
<Button
android:id="@ id/dialog_btn_negative"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="@drawable/common_dialog_negative_seletor"
android:text="@string/common_cancel"
android:textColor="@color/common_dialog_base_text"
android:textSize="@dimen/common_dialog_text_size" />
<View
android:id="@ id/dialog_v_btn_separate"
android:layout_width="@dimen/common_dialog_line_width"
android:layout_height="match_parent"
android:background="@color/common_dialog_base_line" />
<Button
android:id="@ id/dialog_btn_positive"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="@drawable/common_dialog_positive_seletor"
android:text="@string/common_confirm"
android:textColor="@color/default_clickable_text"
android:textSize="@dimen/common_dialog_text_size"
/>
</LinearLayout>
</LinearLayout>
好了,很简单吧,希望对大家有所帮助。