一个简单的Android网络访问全局码判断及通用数据解析方案

本文涉及的产品
全局流量管理 GTM,标准版 1个月
云解析 DNS,旗舰版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
简介: 我们在开发中,网络请求经常会遇到各种错误码的判断。比如下面这样:

我们在开发中,网络请求经常会遇到各种错误码的判断。比如下面这样:

先不说正常的错误码,就项目中的这些码,不可能我们每次都自己去判一遍吧,这样也太麻烦了。刚好实习期间项目中有很多需要的地方,于是写了个简单的小工具。


代码很简单,并没有太多优化,我们在使用时可以按照自己的想法,自由定制,再多的设计模式都只是为了更好的使用,所以不用太过在意,如果考虑优化,那么可以进行更好的封装改造,这里我只是简单给一个解决的思想。


流程大概是这样的:


  1. 首先,创建自己的数据Bean类,GsonGormat一键生成,然后继承于BaseDataBean,利用泛型自由实现我们需求。成功返回我们需要的bean对象,否则弹出失败dialog。
  2. 使用时
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>

好了,很简单吧,希望对大家有所帮助。

目录
相关文章
|
6天前
|
安全 虚拟化
在数字化时代,网络项目的重要性日益凸显。本文从前期准备、方案内容和注意事项三个方面,详细解析了如何撰写一个优质高效的网络项目实施方案,帮助企业和用户实现更好的体验和竞争力
在数字化时代,网络项目的重要性日益凸显。本文从前期准备、方案内容和注意事项三个方面,详细解析了如何撰写一个优质高效的网络项目实施方案,帮助企业和用户实现更好的体验和竞争力。通过具体案例,展示了方案的制定和实施过程,强调了目标明确、技术先进、计划周密、风险可控和预算合理的重要性。
20 5
|
7天前
|
SQL 安全 网络安全
网络安全的护城河:漏洞防御与加密技术的深度解析
【10月更文挑战第37天】在数字时代的浪潮中,网络安全成为守护个人隐私与企业资产的坚固堡垒。本文将深入探讨网络安全的两大核心要素——安全漏洞和加密技术,以及如何通过提升安全意识来强化这道防线。文章旨在揭示网络攻防战的复杂性,并引导读者构建更为稳固的安全体系。
18 1
|
16天前
|
SQL 安全 测试技术
网络安全的盾牌与剑——漏洞防御与加密技术解析
【10月更文挑战第28天】 在数字时代的浪潮中,网络空间安全成为我们不可忽视的战场。本文将深入探讨网络安全的核心问题,包括常见的网络安全漏洞、先进的加密技术以及提升个人和组织的安全意识。通过实际案例分析和代码示例,我们将揭示黑客如何利用漏洞进行攻击,展示如何使用加密技术保护数据,并强调培养网络安全意识的重要性。让我们一同揭开网络安全的神秘面纱,为打造更加坚固的数字防线做好准备。
35 3
RS-485网络中的标准端接与交流电端接应用解析
RS-485,作为一种广泛应用的差分信号传输标准,因其传输距离远、抗干扰能力强、支持多点通讯等优点,在工业自动化、智能建筑、交通运输等领域得到了广泛应用。在构建RS-485网络时,端接技术扮演着至关重要的角色,它直接影响到网络的信号完整性、稳定性和通信质量。
|
6天前
|
网络协议 网络安全 网络虚拟化
本文介绍了十个重要的网络技术术语,包括IP地址、子网掩码、域名系统(DNS)、防火墙、虚拟专用网络(VPN)、路由器、交换机、超文本传输协议(HTTP)、传输控制协议/网际协议(TCP/IP)和云计算
本文介绍了十个重要的网络技术术语,包括IP地址、子网掩码、域名系统(DNS)、防火墙、虚拟专用网络(VPN)、路由器、交换机、超文本传输协议(HTTP)、传输控制协议/网际协议(TCP/IP)和云计算。通过这些术语的详细解释,帮助读者更好地理解和应用网络技术,应对数字化时代的挑战和机遇。
32 3
|
6天前
|
存储 网络协议 安全
30 道初级网络工程师面试题,涵盖 OSI 模型、TCP/IP 协议栈、IP 地址、子网掩码、VLAN、STP、DHCP、DNS、防火墙、NAT、VPN 等基础知识和技术,帮助小白们充分准备面试,顺利踏入职场
本文精选了 30 道初级网络工程师面试题,涵盖 OSI 模型、TCP/IP 协议栈、IP 地址、子网掩码、VLAN、STP、DHCP、DNS、防火墙、NAT、VPN 等基础知识和技术,帮助小白们充分准备面试,顺利踏入职场。
19 2
|
13天前
|
存储 分布式计算 Java
存算分离与计算向数据移动:深度解析与Java实现
【11月更文挑战第10天】随着大数据时代的到来,数据量的激增给传统的数据处理架构带来了巨大的挑战。传统的“存算一体”架构,即计算资源与存储资源紧密耦合,在处理海量数据时逐渐显露出其局限性。为了应对这些挑战,存算分离(Disaggregated Storage and Compute Architecture)和计算向数据移动(Compute Moves to Data)两种架构应运而生,成为大数据处理领域的热门技术。
36 2
|
13天前
|
SQL 安全 算法
网络安全的屏障与钥匙:漏洞防护与加密技术解析
【10月更文挑战第31天】在数字世界的海洋中,网络安全是航船的坚固屏障,而信息安全则是守护宝藏的金钥匙。本文将深入探讨网络安全的薄弱环节——漏洞,以及如何通过加密技术加固这道屏障。从常见网络漏洞的类型到最新的加密算法,我们不仅提供理论知识,还将分享实用的安全实践技巧,帮助读者构建起一道更加坚不可摧的防线。
23 1
|
16天前
|
存储 安全 网络安全
云计算与网络安全:保护数据的新策略
【10月更文挑战第28天】随着云计算的广泛应用,网络安全问题日益突出。本文将深入探讨云计算环境下的网络安全挑战,并提出有效的安全策略和措施。我们将分析云服务中的安全风险,探讨如何通过技术和管理措施来提升信息安全水平,包括加密技术、访问控制、安全审计等。此外,文章还将分享一些实用的代码示例,帮助读者更好地理解和应用这些安全策略。
|
9天前
|
机器学习/深度学习 人工智能 自动驾驶
深入解析深度学习中的卷积神经网络(CNN)
深入解析深度学习中的卷积神经网络(CNN)
26 0

推荐镜像

更多