我们在开发中,网络请求经常会遇到各种错误码的判断。比如下面这样:
先不说正常的错误码,就项目中的这些码,不可能我们每次都自己去判一遍吧,这样也太麻烦了。刚好实习期间项目中有很多需要的地方,于是写了个简单的小工具。
代码很简单,并没有太多优化,我们在使用时可以按照自己的想法,自由定制,再多的设计模式都只是为了更好的使用,所以不用太过在意,如果考虑优化,那么可以进行更好的封装改造,这里我只是简单给一个解决的思想。
流程大概是这样的:
- 首先,创建自己的数据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 这个没得说,随便定义吧,这里我给出一个简单的提示窗口,大家可以随意发挥.
看一下代码,就很简单吧,下面开始上代码:
工具类,自由定义
/** * 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数据类
/** * Created by Petterp * on 2019-10-04 * Function: 统一Gson数据 */ public class BaseDataBean { }
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对话框
/** * 通用对话框 */ 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
<?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>
好了,很简单吧,希望对大家有所帮助。