IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> Android实现动态切换环境配置2.0版本 -> 正文阅读

[移动开发]Android实现动态切换环境配置2.0版本

前言

在上一篇幅《Android在APP开发阶段,实现动态的环境配置切换》 我们实现了可以动态切换环境配置的功能,现在扩展了它的功能,添加了手动输入的URL地址,保存到历史记录列表中,可以从列表选择使用,这样可以在手动输入地址的时候更方便、快捷一些。

先上图

在这里插入图片描述
apk 安装包地址:https://download.csdn.net/download/Silence1515/21059203

项目工程地址:https://download.csdn.net/download/Silence1515/21059232

历史记录功能

??在手动输入URL地址的部分添加了历史记录功能,可以配置常用的地址,如果有手动输入的地址且保存使用,则会缓存在本地,下次中以查看到。历史记录数据,每次会将最近输入的地址放在前面,且地址不会重复,配置的常用地址不会再另外缓存到本地。

??主要看一下修改业务的类:

??UrlHistoryBean 实体类:

package com.windfallsheng.envconfig.bean;

import androidx.annotation.NonNull;
import java.io.Serializable;

/**
 * @Author: lzsheng
 * @date: 2021/8/13 14:17
 * @description:
 */
public class UrlHistoryBean implements Serializable ,Cloneable{

    private String type;
    private String urlStr;

    public UrlHistoryBean(String type, String urlStr) {
        this.type = type;
        this.urlStr = urlStr;
    }

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }

    public String getUrlStr() {
        return urlStr;
    }

    public void setUrlStr(String urlStr) {
        this.urlStr = urlStr;
    }

    @NonNull
    @Override
    protected Object clone() {
        UrlHistoryBean urlHistoryBean = null;
        try {
            urlHistoryBean = (UrlHistoryBean) super.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return urlHistoryBean;
    }

    @Override
    public String toString() {
        return "UrlHistoryBean{" +
                "type='" + type + '\'' +
                ", urlStr='" + urlStr + '\'' +
                '}';
    }
}

??UrlDetailsInputLayout 自定义的URL输入类中的业务变动:

package com.windfallsheng.envconfig.widget;

import android.content.Context;
import android.content.res.TypedArray;
import android.text.Editable;
import android.text.Selection;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.util.AttributeSet;
import android.util.Patterns;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.webkit.URLUtil;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;
import androidx.core.content.ContextCompat;
import com.windfallsheng.envconfig.R;
import com.windfallsheng.envconfig.bean.ServerUrlDetailsBean;
import com.windfallsheng.envconfig.bean.UrlHistoryBean;
import com.windfallsheng.envconfig.dialog.EnvConfigDialogFragment;
import java.net.MalformedURLException;
import java.net.URL;

/**
 * @Author: lzsheng
 * @date: 2021/8/6 17:15
 * @description:
 */
public class UrlDetailsInputLayout extends RelativeLayout {

    private final int INPUT_MAX_LENGTH = 80;
    private Context mContext;
    private View mRootView;
    private LinearLayout mLayoutContent;
    private TextView mTvTypeName;
    private TextView mTvShowUrlHistory;
    private EditText mEtInput;
    private boolean isChecked;
    private CheckBox mCbSelect;
    private String mTypeId;
    private String mTypeName;
    private String mUrlInput;
    private UrlHistoryBean mUrlHistoryBean = new UrlHistoryBean(EnvConfigDialogFragment.URL_HISTORY_TYPE_INPUT, "");
    private OnShowUrlHistoryListener mOnShowUrlHistoryListener;

    public UrlDetailsInputLayout(Context context) {
        super(context);
        init(context, null, 0);
    }

    public UrlDetailsInputLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context, attrs, 0);
    }

    public UrlDetailsInputLayout(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context, attrs, defStyleAttr);
    }

    private void init(Context context, AttributeSet attrs, int defStyleAttr) {
        this.mContext = context;
        mRootView = LayoutInflater.from(context).inflate(R.layout.env_config_layout_url_details_input, null);

        mLayoutContent = mRootView.findViewById(R.id.layout_content);
        mTvTypeName = mRootView.findViewById(R.id.tv_type_name);
        mTvShowUrlHistory = mRootView.findViewById(R.id.tv_show_url_history);
        mEtInput = mRootView.findViewById(R.id.et_input);
        mCbSelect = mRootView.findViewById(R.id.cb_selecte);
        addView(mRootView);

        mRootView.setLayoutParams(new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));

        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.url_details_input_layout);
        mTypeId = typedArray.getString(R.styleable.url_details_input_layout_type_id);
        mTypeName = typedArray.getString(R.styleable.url_details_input_layout_type_name);
        mUrlInput = typedArray.getString(R.styleable.url_details_input_layout_url_input);
        isChecked = typedArray.getBoolean(R.styleable.url_details_input_layout_is_checked, false);
        int bgColor = typedArray.getColor(R.styleable.url_details_input_layout_item_bg, ContextCompat.getColor(mContext, R.color.white));
        typedArray.recycle();

        mLayoutContent.setBackgroundColor(bgColor);
        mTvTypeName.setText(mTypeName);
        if (!TextUtils.isEmpty(mUrlInput)) {
            mEtInput.setText(mUrlInput);
        }
        mEtInput.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {

            }

            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {
                String str = s.toString().trim();
                Editable editable = mEtInput.getText();
                if (str.length() > INPUT_MAX_LENGTH) {
                    Toast.makeText(mContext, "超过80个字符的输入限制", Toast.LENGTH_SHORT).show();
                    int selEndIndex = Selection.getSelectionEnd(editable);
                    //截取新字符串
                    String newStr = str.substring(0, INPUT_MAX_LENGTH);
                    mEtInput.setText(newStr);
                    editable = mEtInput.getText();

                    //新字符串的长度
                    int newLen = editable.length();
                    //旧光标位置超过字符串长度
                    if (selEndIndex > newLen) {
                        selEndIndex = editable.length();
                    }
                    //设置新光标所在的位置
                    Selection.setSelection(editable, selEndIndex);
                }
            }

            @Override
            public void afterTextChanged(Editable s) {

            }
        });
        mCbSelect.setChecked(isChecked);

        mLayoutContent.setOnClickListener(v -> {
            isChecked = !isChecked;
            mCbSelect.setChecked(isChecked);
        });
        mTvShowUrlHistory.setOnClickListener(v -> {
            if (mOnShowUrlHistoryListener != null) {
                mOnShowUrlHistoryListener.onShowUrlHistory(v);
            }
        });

    }

    public void setShowHistoryViewId(int id) {
        mTvShowUrlHistory.setId(id);
    }

    public boolean isChecked() {
        return isChecked;
    }

    public void setChecked(boolean isChecked) {
        this.isChecked = isChecked;
        if (mCbSelect != null) {
            mCbSelect.setChecked(this.isChecked);
        }
    }

    public String getTypeName() {
        return mTypeName;
    }

    public void setOnShowUrlHistoryListener(OnShowUrlHistoryListener onShowUrlHistoryListener) {
        this.mOnShowUrlHistoryListener = onShowUrlHistoryListener;
    }

    /**
     *
     */
    public void setUrlInput(UrlHistoryBean urlHistoryBean) {
        if (urlHistoryBean != null) {
            mUrlHistoryBean = urlHistoryBean;
            String urlStr = urlHistoryBean.getUrlStr();
            if (!TextUtils.isEmpty(urlStr)) {
                mEtInput.setText(urlStr);
            }
        }
    }

    /**
     * 获取数据 ServerUrlDetailsBean 实例,如果网址输入无效则返回 null;
     */
    public ServerUrlDetailsBean getUrlDetailBean() {
        String urlInput = mEtInput.getText().toString().trim();
        if (!TextUtils.isEmpty(urlInput) && isUrlValid(urlInput)) {
            if (mUrlHistoryBean != null) {
                String urlStr = mUrlHistoryBean.getUrlStr();
                if (TextUtils.equals(urlInput, urlStr)) {
                    // 如果url地址相同,暂不处理;
                } else {
                    // 如果url地址不同,需要修改类型,并且重新赋值;
                    mUrlHistoryBean.setUrlStr(urlInput);
                    mUrlHistoryBean.setType(EnvConfigDialogFragment.URL_HISTORY_TYPE_INPUT);
                }
            }
            return new ServerUrlDetailsBean(mTypeId, mUrlHistoryBean, mTypeName, mCbSelect.isChecked());
        }
        return null;
    }

    /**
     * 重置所有数据及UI
     */
    public void resetData() {
        mCbSelect.setChecked(false);
        isChecked = false;
        mEtInput.setText("");
        mUrlInput = "";
    }

    /**
     * 网址是否有效
     */
    private boolean isUrlValid(String urlString) {
        try {
            URL url = new URL(urlString);
            return URLUtil.isValidUrl(urlString) && Patterns.WEB_URL.matcher(urlString).matches();
        } catch (MalformedURLException e) {

        }
        return false;
    }

    public interface OnShowUrlHistoryListener {

        void onShowUrlHistory(View v);
    }

}

??UrlDetailsInputLayout 类修改了 UI 的样式和交互逻辑,以及处理手动输入URL的逻辑。
??相应的 xml布局调整:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/layout_content"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:gravity="center_vertical"
    android:orientation="horizontal">

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:orientation="vertical">

        <RelativeLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="1">

            <TextView
                android:id="@+id/tv_type_name"
                android:layout_width="wrap_content"
                android:layout_height="30dp"
                android:layout_centerVertical="true"
                android:layout_marginLeft="15dp"
                android:layout_marginTop="15dp"
                android:gravity="center_vertical"
                android:textColor="@color/green_008c8c"
                android:textSize="15sp"
                tools:text="H5服务器地址" />

            <TextView
                android:id="@+id/tv_show_url_history"
                android:layout_width="wrap_content"
                android:layout_height="30dp"
                android:layout_alignParentRight="true"
                android:layout_centerVertical="true"
                android:layout_marginTop="15dp"
                android:layout_marginRight="15dp"
                android:background="@drawable/layout_item_bg"
                android:gravity="center_vertical"
                android:paddingLeft="10dp"
                android:paddingRight="10dp"
                android:text="历史记录"
                android:textColor="@color/green_008c8c"
                android:textSize="15sp" />

        </RelativeLayout>


        <EditText
            android:id="@+id/et_input"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginLeft="15dp"
            android:layout_marginTop="5dp"
            android:layout_marginBottom="10dp"
            android:hint="请输入地址(最长可输入80个字符)"
            android:textColorHint="@color/gray_c3c3c3"
            android:textColor="@color/app_text_color"
            android:textSize="15sp" />

    </LinearLayout>


    <CheckBox
        android:id="@+id/cb_selecte"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:clickable="false" />

</LinearLayout>

??EnvConfigDialogFragment 类中配置的 json 格式略微做了些调整,还有新增的 配置 json。另外,与历史记录相关的业务做了调整;

package com.windfallsheng.envconfig.dialog;

import android.app.Dialog;
import android.content.Context;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.widget.FrameLayout;
import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.windfallsheng.envconfig.EnvConfigHelper;
import com.windfallsheng.envconfig.EnvServerUrlConsts;
import com.windfallsheng.envconfig.R;
import com.windfallsheng.envconfig.bean.AllServerUrlDetailsBean;
import com.windfallsheng.envconfig.bean.AppInfoBean;
import com.windfallsheng.envconfig.bean.EnvConfigBean;
import com.windfallsheng.envconfig.bean.EnvConfigWrapper;
import com.windfallsheng.envconfig.bean.ServerUrlDetailsBean;
import com.windfallsheng.envconfig.bean.UrlHistoryBean;
import com.windfallsheng.envconfig.widget.UrlDetailsInputLayout;
import com.windfallsheng.lib.Consts;
import com.windfallsheng.lib.util.DisplayHelper;
import com.windfallsheng.lib.util.LogUtils;
import com.windfallsheng.lib.util.ResUtils;
import com.windfallsheng.lib.util.SharedPrefsManager;
import java.util.ArrayList;
import java.util.List;

/**
 * @Author: lzsheng
 * @CreateDate: 2020/12/16 14:54
 * @LastModifiedTime: 2020/12/16 14:54
 * @Description:
 */
public class EnvConfigDialogFragment extends BaseDialogFragment implements UrlDetailsInputLayout.OnShowUrlHistoryListener {

    public static final int VIEW_TYPE_SERVER_URL_DETAILS = 1;
    public static final int VIEW_TYPE_AD = 2;
    public static final int VIEW_TYPE_WEB = 3;
    public static final int VIEW_TYPE_FIRST_INSTALL = 4;
    public static final int VIEW_TYPE_LOG_DEBUG = 5;
    /**
     * 默认的URL
     */
    public static final String URL_HISTORY_TYPE_DEFAULT = "default";
    /**
     * 手动输入的URL
     */
    public static final String URL_HISTORY_TYPE_INPUT = "input";
    /**
     * URL的分类标题
     */
    public static final String URL_HISTORY_TYPE_TITLE = "url_history_type_title";
    /**
     *
     */
    private static final String MODE_VALUE_LAST_SELECTED = "mode_value_last_selected";
    private static final String ENV_CONFIG_WRAPPER_DEFAULT = "env_config_wrapper_default";
    private final boolean CHECKED = true;
    private final boolean UNCHECKED = false;
    private final boolean REQUIRED = true;
    private final boolean UNREQUIRED = false;
    private final boolean GROUP = true;
    private final boolean NO_GROUP = false;
    private final String GROUP_ID_SERVER_URL_DETAILS = "server_url_details";
    private final String GROUP_ID_SKIP_AD_PAGE = "skip_ad_page";
    private final String GROUP_ID_FIRST_INSTALL = "first_install";
    private final String GROUP_ID_LOG_DEBUG = "log_debug";
    private final String TAG = "AppConfigDialogFragment";
    /**
     * 根据需要修改配置数据的json串;
     */
    private final String configJsonAllServerDetails = "[" +
            "{" +
            "\"configId\":\"dev_test_server_url_details\"," +
            "\"groupId\":\"" + GROUP_ID_SERVER_URL_DETAILS + "\"," +
            "\"modeOfEnv\":\"" + EnvConfigHelper.EnvMode.DEV_TEST_SERVER.getMode() + "\"," +
            "\"labelName\":\"测试环境(测试服务器)\"," +
            "\"isChecked\":" + CHECKED + "," +
            "\"isRequired\":" + REQUIRED + "," +
            "\"isGroup\":" + GROUP + "," +
            "\"viewType\":" + VIEW_TYPE_SERVER_URL_DETAILS + "," +

            "\"apiServerUrlDetails\":" +
            "{" +
            "\"typeId\":\"api\"," +
            "\"typeName\":\"API服务器地址\"," +

            "\"urlHistoryBean\":" +
            "{" +
            "\"type\":\"" + URL_HISTORY_TYPE_DEFAULT + "\"," +
            "\"urlStr\":\"" + EnvServerUrlConsts.TestServer.API_SERVER + "\"" +
            "}" +

            "}," +
            "\"imageServerUrlDetails\":" +
            "{" +
            "\"typeId\":\"image\"," +
            "\"typeName\":\"image服务器地址\"," +

            "\"urlHistoryBean\":" +
            "{" +
            "\"type\":\"" + URL_HISTORY_TYPE_DEFAULT + "\"," +
            "\"urlStr\":\"" + EnvServerUrlConsts.TestServer.IMAGE_SERVER + "\"" +
            "}" +

            "}," +
            "\"h5ServerUrlDetails\":" +
            "{" +
            "\"typeId\":\"h5\"," +
            "\"typeName\":\"H5服务器地址\"," +

            "\"urlHistoryBean\":" +
            "{" +
            "\"type\":\"" + URL_HISTORY_TYPE_DEFAULT + "\"," +
            "\"urlStr\":\"" + EnvServerUrlConsts.TestServer.H5_SERVER + "\"" +
            "}" +

            "}" +

            "}," +
            "{" +
            "\"configId\":\"dev_test_local_server_url_details\"," +
            "\"groupId\":\"" + GROUP_ID_SERVER_URL_DETAILS + "\"," +
            "\"labelName\":\"本地测试环境(本地地址)\"," +
            "\"modeOfEnv\":\"" + EnvConfigHelper.EnvMode.DEV_TEST_LOCAL.getMode() + "\"," +
            "\"isChecked\":" + UNCHECKED + "," +
            "\"isRequired\":" + REQUIRED + "," +
            "\"isGroup\":" + GROUP + "," +
            "\"viewType\":" + VIEW_TYPE_SERVER_URL_DETAILS + "," +

            "\"apiServerUrlDetails\":" +
            "{" +
            "\"typeId\":\"api\"," +
            "\"typeName\":\"API服务器地址\"," +

            "\"urlHistoryBean\":" +
            "{" +
            "\"type\":\"" + URL_HISTORY_TYPE_DEFAULT + "\"," +
            "\"urlStr\":\"" + EnvServerUrlConsts.TestLocal.API_SERVER + "\"" +
            "}" +

            "}," +
            "\"imageServerUrlDetails\":" +
            "{" +
            "\"typeId\":\"image\"," +
            "\"typeName\":\"image服务器地址\"," +

            "\"urlHistoryBean\":" +
            "{" +
            "\"type\":\"" + URL_HISTORY_TYPE_DEFAULT + "\"," +
            "\"urlStr\":\"" + EnvServerUrlConsts.TestLocal.IMAGE_SERVER + "\"" +
            "}" +

            "}," +
            "\"h5ServerUrlDetails\":" +
            "{" +
            "\"typeId\":\"h5\"," +
            "\"typeName\":\"H5服务器地址\"," +

            "\"urlHistoryBean\":" +
            "{" +
            "\"type\":\"" + URL_HISTORY_TYPE_DEFAULT + "\"," +
            "\"urlStr\":\"" + EnvServerUrlConsts.TestLocal.H5_SERVER + "\"" +
            "}" +

            "}" +

            "}," +
            "{" +
            "\"configId\":\"dev_pilot_server_url_details\"," +
            "\"groupId\":\"" + GROUP_ID_SERVER_URL_DETAILS + "\"," +
            "\"labelName\":\"试运行环境\"," +
            "\"modeOfEnv\":\"" + EnvConfigHelper.EnvMode.DEV_PILOT_RUN.getMode() + "\"," +
            "\"isChecked\":" + UNCHECKED + "," +
            "\"isRequired\":" + REQUIRED + "," +
            "\"isGroup\":" + GROUP + "," +
            "\"viewType\":" + VIEW_TYPE_SERVER_URL_DETAILS + "," +

            "\"apiServerUrlDetails\":" +
            "{" +
            "\"typeId\":\"api\"," +
            "\"typeName\":\"API服务器地址\"," +

            "\"urlHistoryBean\":" +
            "{" +
            "\"type\":\"" + URL_HISTORY_TYPE_DEFAULT + "\"," +
            "\"urlStr\":\"" + EnvServerUrlConsts.PilotRun.API_SERVER + "\"" +
            "}" +

            "}," +
            "\"imageServerUrlDetails\":" +
            "{" +
            "\"typeId\":\"image\"," +
            "\"typeName\":\"image服务器地址\"," +

            "\"urlHistoryBean\":" +
            "{" +
            "\"type\":\"" + URL_HISTORY_TYPE_DEFAULT + "\"," +
            "\"urlStr\":\"" + EnvServerUrlConsts.PilotRun.IMAGE_SERVER + "\"" +
            "}" +

            "}," +
            "\"h5ServerUrlDetails\":" +
            "{" +
            "\"typeId\":\"h5\"," +
            "\"typeName\":\"H5服务器地址\"," +

            "\"urlHistoryBean\":" +
            "{" +
            "\"type\":\"" + URL_HISTORY_TYPE_DEFAULT + "\"," +
            "\"urlStr\":\"" + EnvServerUrlConsts.PilotRun.H5_SERVER + "\"" +
            "}" +

            "}" +

            "}," +
            "{" +
            "\"configId\":\"dev_product_server_url_details\"," +
            "\"groupId\":\"" + GROUP_ID_SERVER_URL_DETAILS + "\"," +
            "\"modeOfEnv\":\"" + EnvConfigHelper.EnvMode.DEV_PRODUCT.getMode() + "\"," +
            "\"labelName\":\"生产环境\"," +
            "\"isChecked\":" + UNCHECKED + "," +
            "\"isRequired\":" + REQUIRED + "," +
            "\"isGroup\":" + GROUP + "," +
            "\"viewType\":" + VIEW_TYPE_SERVER_URL_DETAILS + "," +

            "\"apiServerUrlDetails\":" +
            "{" +
            "\"typeId\":\"api\"," +
            "\"typeName\":\"API服务器地址\"," +

            "\"urlHistoryBean\":" +
            "{" +
            "\"type\":\"" + URL_HISTORY_TYPE_DEFAULT + "\"," +
            "\"urlStr\":\"" + EnvServerUrlConsts.Product.API_SERVER + "\"" +
            "}" +

            "}," +
            "\"imageServerUrlDetails\":" +
            "{" +
            "\"typeId\":\"image\"," +
            "\"typeName\":\"image服务器地址\"," +

            "\"urlHistoryBean\":" +
            "{" +
            "\"type\":\"" + URL_HISTORY_TYPE_DEFAULT + "\"," +
            "\"urlStr\":\"" + EnvServerUrlConsts.Product.IMAGE_SERVER + "\"" +
            "}" +

            "}," +
            "\"h5ServerUrlDetails\":" +
            "{" +
            "\"typeId\":\"h5\"," +
            "\"typeName\":\"H5服务器地址\"," +

            "\"urlHistoryBean\":" +
            "{" +
            "\"type\":\"" + URL_HISTORY_TYPE_DEFAULT + "\"," +
            "\"urlStr\":\"" + EnvServerUrlConsts.Product.H5_SERVER + "\"" +
            "}" +

            "}" +

            "}" +
            "]";

    /**
     * 根据需要修改配置数据的json串;
     */
    private final String configJsonSimple = "[" +
            "{" +
            "\"configId\":\"first_install\"," +
            "\"groupId\":\"" + GROUP_ID_FIRST_INSTALL + "\"," +
            "\"labelName\":\"是否为首次安装启动(选中代表是)\"," +
            "\"isChecked\":" + UNCHECKED + "," +
            "\"isRequired\":" + UNREQUIRED + "," +
            "\"isGroup\":" + NO_GROUP + "," +
            "\"viewType\":" + VIEW_TYPE_FIRST_INSTALL +
            "}," +
            "{" +
            "\"configId\":\"log_debug\"," +
            "\"groupId\":\"" + GROUP_ID_LOG_DEBUG + "\"," +
            "\"labelName\":\"是否关闭Log日志(选中代表关闭)\"," +
            "\"isChecked\":" + UNCHECKED + "," +
            "\"isRequired\":" + UNREQUIRED + "," +
            "\"isGroup\":" + NO_GROUP + "," +
            "\"viewType\":" + VIEW_TYPE_LOG_DEBUG +
            "}," +
            "{" +
            "\"configId\":\"skip_ad_page\"," +
            "\"groupId\":\"" + GROUP_ID_SKIP_AD_PAGE + "\"," +
            "\"labelName\":\"是否跳过广告页(选中代表是)\"," +
            "\"isChecked\":" + UNCHECKED + "," +
            "\"isRequired\":" + UNREQUIRED + "," +
            "\"isGroup\":" + NO_GROUP + "," +
            "\"viewType\":" + VIEW_TYPE_AD +
            "}" +
            "]";
    private String urlHistoryDefaultJson = "[" +
            "{" +
            "\"type\":\"" + URL_HISTORY_TYPE_DEFAULT + "\"," +
            "\"urlStr\":" + "\"https://history.url.temp.aa.com.cn:998\"" +
            "}," +
            "{" +
            "\"type\":\"" + URL_HISTORY_TYPE_DEFAULT + "\"," +
            "\"urlStr\":" + "\"https://history.url.temp.bb.com.cn:998\"" +
            "}," +
            "{" +
            "\"type\":\"" + URL_HISTORY_TYPE_DEFAULT + "\"," +
            "\"urlStr\":" + "\"https://history.url.temp.cc.com.cn:998\"" +
            "}," +
            "{" +
            "\"type\":\"" + URL_HISTORY_TYPE_DEFAULT + "\"," +
            "\"urlStr\":" + "\"https://history.url.temp.dd.com.cn:998\"" +
            "}" +
            "]";
    private View rootView;
    private RecyclerView mRecyclerView;
    private TextView tvCheckDetails;
    private TextView tvEnvDetails;
    private TextView tvFinish;
    private TextView tvResetAllConfig;
    private EnvConfigAdapter mEnvConfigAdapter;
    private List<EnvConfigBean> mEnvConfigList;
    /**
     * 手动输入URL的UI部分;
     */
    private UrlDetailsInputLayout mUrlInputLayoutApi;
    private UrlDetailsInputLayout mUrlInputLayoutImage;
    private UrlDetailsInputLayout mUrlInputLayoutH5;

    /**
     * 传入的配置项或者上次缓存的配置项;
     */
    private EnvConfigWrapper mEnvConfigWrapperDefault;
    private EnvConfigCheckedCompleteListener mEnvConfigCheckedCompleteListener;

    public static EnvConfigDialogFragment newInstance() {
        return newInstance(null);
    }

    public static EnvConfigDialogFragment newInstance(EnvConfigWrapper envConfigWrapper) {
        EnvConfigDialogFragment fragment = new EnvConfigDialogFragment();
        Bundle args = new Bundle();
        args.putSerializable(ENV_CONFIG_WRAPPER_DEFAULT, envConfigWrapper);
        fragment.setArguments(args);
        return fragment;
    }

    @Override
    public void onAttach(Context context) {
        mContext = context;
        super.onAttach(context);
        if (getArguments() != null) {
            mEnvConfigWrapperDefault = (EnvConfigWrapper) getArguments().getSerializable(ENV_CONFIG_WRAPPER_DEFAULT);
        }
        // 如果入参没有配置项,则查看有没有本地缓存;
        if (mEnvConfigWrapperDefault == null) {
            // 暂时使用 SharedPreferences 作为本地缓存,根据实际需要选择处理方式;
            mEnvConfigWrapperDefault = EnvConfigHelper.getInstance().initEnvConfigWrapper();
        }

        LogUtils.dl(TAG, "method:onAttach#mEnvConfigWrapperDefault=" + mEnvConfigWrapperDefault);
        try {
            mEnvConfigCheckedCompleteListener = (EnvConfigCheckedCompleteListener) context;
        } catch (ClassCastException e) {
            LogUtils.el(TAG, "method:onAttach#exception=" + e.getMessage());
        }
    }

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        getDialog().getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
        rootView = inflater.inflate(R.layout.env_config_layout_fragment_dialog, container, false);
        mRecyclerView = rootView.findViewById(R.id.recyclerview_config);
        tvCheckDetails = rootView.findViewById(R.id.tv_check_details);
        tvEnvDetails = rootView.findViewById(R.id.tv_env_config_details);
        tvFinish = rootView.findViewById(R.id.tv_finish);
        tvResetAllConfig = rootView.findViewById(R.id.tv_reset_config);
        mUrlInputLayoutApi = rootView.findViewById(R.id.url_details_layout_api);
        mUrlInputLayoutImage = rootView.findViewById(R.id.url_details_layout_image);
        // 设置ID;
        mUrlInputLayoutH5 = rootView.findViewById(R.id.url_details_layout_h5);
        mUrlInputLayoutApi.setShowHistoryViewId(R.id.url_detail_input_api_id);
        mUrlInputLayoutImage.setShowHistoryViewId(R.id.url_detail_input_image_id);
        mUrlInputLayoutH5.setShowHistoryViewId(R.id.url_detail_input_h5_id);
        return rootView;
    }

    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        // 调整布局的宽高
        ViewGroup.LayoutParams layoutParams = rootView.getLayoutParams();
        layoutParams.height = (int) (DisplayHelper.getScreenHeight(mContext) * 0.8);
        layoutParams.width = (int) (DisplayHelper.getScreenWidth(mContext) * 0.8);
        rootView.setLayoutParams(layoutParams);
        FrameLayout parent = (FrameLayout) rootView.getParent();
        parent.setBackgroundResource(R.color.transparent);

        LinearLayoutManager mLinearLayoutManager = new LinearLayoutManager(mContext);
        mRecyclerView.setLayoutManager(mLinearLayoutManager);
        mRecyclerView.setNestedScrollingEnabled(false);

        mEnvConfigList = initListDataFromJson();
        // 如果最近一次的选中数据,则修改默认选中项;
        initEnvConfigListDataAndViews(mEnvConfigList);

        mEnvConfigAdapter = new EnvConfigAdapter();
        mEnvConfigAdapter.addAll(mEnvConfigList);
        mRecyclerView.setAdapter(mEnvConfigAdapter);
        // 行点击事件
        mEnvConfigAdapter.setOnRecyclerViewItemClick((EnvConfigAdapter.OnRecyclerViewItemClick<EnvConfigBean>)
                (childView, position, envConfigBean) -> {
                    updateListData(position, envConfigBean);
                    mEnvConfigAdapter.notifyDataSetChanged();
                });
        // 重置配置项事件;
        tvResetAllConfig.setOnClickListener(v -> {
            handleResetAllConfig();
        });

        tvCheckDetails.setOnClickListener(v -> {
            showAllConfigDetails();
        });

        mUrlInputLayoutApi.setOnShowUrlHistoryListener(EnvConfigDialogFragment.this);
        mUrlInputLayoutImage.setOnShowUrlHistoryListener(EnvConfigDialogFragment.this);
        mUrlInputLayoutH5.setOnShowUrlHistoryListener(EnvConfigDialogFragment.this);

        tvFinish.setOnClickListener(v -> handlerFinishClicked());
    }


    @Override
    public void onShowUrlHistory(View v) {
        List<UrlHistoryBean> urlList = initUrlHistoryListFromJson();
        new SingleSelectionDialog.Builder(mContext)
                .setTitle(R.string.title_select_url)
                .setUrlHistoryList(urlList)
                .setOnUrlSelecteComplete((dialog, childView, position, urlHistoryBean) -> {
                    int id = v.getId();
                    if (id == R.id.url_detail_input_api_id) {
                        mUrlInputLayoutApi.setUrlInput(urlHistoryBean);
                        mUrlInputLayoutApi.setChecked(true);
                    } else if (id == R.id.url_detail_input_image_id) {
                        mUrlInputLayoutImage.setUrlInput(urlHistoryBean);
                        mUrlInputLayoutImage.setChecked(true);
                    } else if (id == R.id.url_detail_input_h5_id) {
                        mUrlInputLayoutH5.setUrlInput(urlHistoryBean);
                        mUrlInputLayoutH5.setChecked(true);
                    }
                    dialog.dismiss();
                })
                .setOnCloseClickedListener(dialog -> {
                    dialog.dismiss();
                })
                .create()
                .show();
    }

    private List<EnvConfigBean> initListDataFromJson() {
        Gson gson = new Gson();
        List<EnvConfigBean> list = new ArrayList<>();
        // 可以选择从 default_config_server_url_details.json 中读取配置;
        List<AllServerUrlDetailsBean> serverList = gson.fromJson(configJsonAllServerDetails, new TypeToken<List<AllServerUrlDetailsBean>>() {
        }.getType());
        list.addAll(serverList);
        List<EnvConfigBean> cofigList = gson.fromJson(configJsonSimple, new TypeToken<List<EnvConfigBean>>() {
        }.getType());
        list.addAll(cofigList);
        return list;
    }


    private List<UrlHistoryBean> initUrlHistoryListFromJson() {
        Gson gson = new Gson();
        List<UrlHistoryBean> list = new ArrayList<>();
        // 可以选择从 default_config_server_url_details.json 中读取配置;
        List<UrlHistoryBean> serverList = gson.fromJson(urlHistoryDefaultJson, new TypeToken<List<UrlHistoryBean>>() {
        }.getType());
        list.add(new UrlHistoryBean(URL_HISTORY_TYPE_TITLE, "常用地址:"));
        list.addAll(serverList);
        list.add(new UrlHistoryBean(URL_HISTORY_TYPE_TITLE, "最近输入地址:"));

        // 本地缓存;
        SharedPrefsManager sharedPrefsManager = SharedPrefsManager.getInstance()
                .init(mContext, Consts.ENV_CONFIG.ENV_CONFIG_SP);
        String json = sharedPrefsManager
                .getString(Consts.ENV_CONFIG.URL_INPUT_HISTORY_JSON);
        if (!TextUtils.isEmpty(json)) {
            List<UrlHistoryBean> inputUrlList = null;
            try {
                inputUrlList = gson.fromJson(json, new TypeToken<List<UrlHistoryBean>>() {
                }.getType());
            } catch (Exception e) {
                LogUtils.el(TAG, e.getMessage());
                sharedPrefsManager.removeKey(Consts.ENV_CONFIG.URL_INPUT_HISTORY_JSON);
            }
            if (inputUrlList != null && inputUrlList.size() > 0) {
                list.addAll(inputUrlList);
            }
        }
        return list;
    }

    private List<EnvConfigBean> getListDataFromJson() {
        List<EnvConfigBean> list = null;
        try {
            String jsonStr = ResUtils.getJsonStr(mContext, "default_config_server_url_details.json");
            Gson gson = new Gson();
            list = gson.fromJson(jsonStr, new TypeToken<List<EnvConfigBean>>() {
            }.getType());
        } catch (Exception e) {
            LogUtils.el(TAG, e.getMessage());
        }
        return list;
    }

    private void showAllConfigDetails() {
        EnvConfigWrapper envConfigWrapper = buildEnvConfigWrapper();
//        String modeValueBuild = envConfigWrapper.getModeOfBuild();
        AllServerUrlDetailsBean allServerUrlDetailsOfCheckedEnv = envConfigWrapper.getAllServerUrlDetailsOfCheckedEnv();

        StringBuilder builder = new StringBuilder();
        //
        AppInfoBean appInfoBean = EnvConfigHelper.getInstance().getAppInfoBean();
        if (appInfoBean != null) {
            builder
                    .append("★★★BuildConfig部分★★★").append("\n\n")
                    .append("★BuildConfig#APPLICATION_ID=").append(appInfoBean.getApplicationId()).append("★\n\n")
                    .append("★BuildConfig#VERSION_CODE=").append(appInfoBean.getVersionCode()).append("★\n\n")
                    .append("★BuildConfig#VERSION_NAME=").append(appInfoBean.getVersionName()).append("★\n\n")
                    .append("★BuildConfig#BUILD_TYPE=").append(appInfoBean.getBuildType()).append("★\n\n")
                    .append("★BuildConfig#FLAVOR=").append(appInfoBean.getFlavor()).append("★\n\n")
                    .append("★BuildConfig#DEBUG=").append(appInfoBean.isDebug()).append("★\n\n")
                    .append("★BuildConfig#LOG_DEBUG=").append(appInfoBean.isLogDebug()).append("★\n\n")
                    .append("★打包模式modeOfBuild=").append(appInfoBean.getModeOfBuild()).append("★\n\n");

        } else {
            LogUtils.el(TAG, "method:showAllConfigDetails#EnvConfigHelper#mAppInfoBean not initialize.");
        }
//        实际的环境情况:
        builder
                .append("★★★当前使用的地址★★★").append("\n\n")
                .append("★api服务器地址:").append(EnvServerUrlConsts.API_SERVER).append("★\n\n")
                .append("★image服务器地址:").append(EnvServerUrlConsts.IMAGE_SERVER).append("★\n\n")
                .append("★H5服务器地址:").append(EnvServerUrlConsts.H5_SERVER).append("★\n\n");
//
        builder
//                .append("BuildConfig部分:").append("\n\n")
//                .append("BuildConfig#APPLICATION_ID=").append(BuildConfig.APPLICATION_ID).append("\n\n")
//                .append("BuildConfig#VERSION_CODE=").append(BuildConfig.VERSION_CODE).append("\n\n")
//                .append("BuildConfig#VERSION_NAME=").append(BuildConfig.VERSION_NAME).append("\n\n")
//                .append("BuildConfig#BUILD_TYPE=").append(BuildConfig.BUILD_TYPE).append("\n\n")
//                .append("BuildConfig#FLAVOR=").append(BuildConfig.FLAVOR).append("\n\n")
//                .append("BuildConfig#DEBUG=").append(BuildConfig.DEBUG).append("\n\n")
//                .append("BuildConfig#LOG_DEBUG=").append(BuildConfig.LOG_DEBUG).append("\n\n")
                .append("★★★修改配置后部分★★★").append("\n\n");

        if (allServerUrlDetailsOfCheckedEnv != null) {
            builder
                    .append("★").append(allServerUrlDetailsOfCheckedEnv.getLabelName()).append("=").append(allServerUrlDetailsOfCheckedEnv.getChecked()).append("★\n\n")
                    .append("★").append("modeOfCurrentEnv=").append(allServerUrlDetailsOfCheckedEnv.getModeOfEnv()).append("★\n\n");

            ServerUrlDetailsBean apiDetailsSelected = envConfigWrapper.getApiServerUrlDetailsInput();
            // 手动输入且被选中的URL的优先级高于环境配置内的URL地址,优先使用手动输入的URL
            if (apiDetailsSelected == null || !apiDetailsSelected.isChecked()) {
                apiDetailsSelected = allServerUrlDetailsOfCheckedEnv.getApiServerUrlDetails();
            }
            if (apiDetailsSelected != null) {
                UrlHistoryBean urlHistoryBean = apiDetailsSelected.getUrlHistoryBean();
                String urlStr = null;
                if (urlHistoryBean != null) {
                    urlStr = urlHistoryBean.getUrlStr();
                }
                builder
                        .append("★").append(apiDetailsSelected.getTypeName()).append("=").append(urlStr).append("★\n\n");
            }
            ServerUrlDetailsBean imageDetailsSelected = envConfigWrapper.getImageServerUrlDetailsInput();
            if (imageDetailsSelected == null || !imageDetailsSelected.isChecked()) {
                imageDetailsSelected = allServerUrlDetailsOfCheckedEnv.getImageServerUrlDetails();
            }
            if (imageDetailsSelected != null) {
                UrlHistoryBean urlHistoryBean = imageDetailsSelected.getUrlHistoryBean();
                String urlStr = null;
                if (urlHistoryBean != null) {
                    urlStr = urlHistoryBean.getUrlStr();
                }
                builder
                        .append("★").append(imageDetailsSelected.getTypeName()).append("=").append(urlStr).append("★\n\n");
            }
            ServerUrlDetailsBean h5DetailsSelected = envConfigWrapper.getH5ServerUrlDetailsInput();
            if (h5DetailsSelected == null || !h5DetailsSelected.isChecked()) {
                h5DetailsSelected = allServerUrlDetailsOfCheckedEnv.getH5ServerUrlDetails();
            }
            if (h5DetailsSelected != null) {
                UrlHistoryBean urlHistoryBean = h5DetailsSelected.getUrlHistoryBean();
                String urlStr = null;
                if (urlHistoryBean != null) {
                    urlStr = urlHistoryBean.getUrlStr();
                }
                builder
                        .append("★").append(h5DetailsSelected.getTypeName()).append("=").append(urlStr).append("★\n\n");
            }
        }

        EnvConfigBean firstInstall = envConfigWrapper.getFirstInstall();
        if (firstInstall != null) {
            builder
                    .append("★").append(firstInstall.getLabelName()).append("=").append(firstInstall.getChecked()).append("★\n\n");
        }
        EnvConfigBean logDebug = envConfigWrapper.getLogDebug();
        if (logDebug != null) {
            builder
                    .append("★").append(logDebug.getLabelName()).append("=").append(logDebug.getChecked()).append("★\n\n");
        }
        EnvConfigBean skipAdPage = envConfigWrapper.getSkipAdPage();
        if (skipAdPage != null) {
            builder
                    .append("★").append(skipAdPage.getLabelName()).append("=").append(skipAdPage.getChecked()).append("★\n\n");
        }
        String allConfigDetailsStr = builder.toString();
        LogUtils.dl(TAG, "method:showAllConfigDetails#allConfigDetailsStr=" + allConfigDetailsStr);

        tvEnvDetails.setText(allConfigDetailsStr);
    }

    /**
     * 重置所有配置项及UI效果;
     */
    private void handleResetAllConfig() {
        SharedPrefsManager.getInstance()
                .init(mContext, Consts.ENV_CONFIG.ENV_CONFIG_SP)
                .removeKey(Consts.ENV_CONFIG.ENV_CONFIG_WRAPPER_JSON);

        mEnvConfigWrapperDefault = null;
        mEnvConfigList = initListDataFromJson();
        //
        initEnvConfigListDataAndViews(mEnvConfigList);
        mEnvConfigAdapter.addNewAll(mEnvConfigList);

        mEnvConfigAdapter.notifyDataSetChanged();

        if (mUrlInputLayoutApi != null) {
            mUrlInputLayoutApi.resetData();
        }
        if (mUrlInputLayoutImage != null) {
            mUrlInputLayoutImage.resetData();
        }
        if (mUrlInputLayoutH5 != null) {
            mUrlInputLayoutH5.resetData();
        }

        tvCheckDetails.performClick();
    }

    /**
     * 如果最近一次的选中数据有值,则修改默认选中项,如果没有则按默认项处理;
     *
     * @param envConfigBeanList
     */
    private void initEnvConfigListDataAndViews(List<EnvConfigBean> envConfigBeanList) {
        if (mEnvConfigWrapperDefault == null) {
            // 当前逻辑分支和json中的默认配置相同,可以不必再执行;
            // 没有设定默认的配置时,根据构建环境进行默认处理;
            handleInitEnvConfigListDataAndViews(envConfigBeanList);
        } else {
            // 有默认配置项时
            handleInitEnvConfigListDataWithDefault(envConfigBeanList);
        }
    }

    private void handleInitEnvConfigListDataWithDefault(List<EnvConfigBean> envConfigBeanList) {
        AllServerUrlDetailsBean allServerUrlDetailsOfCheckedEnv = mEnvConfigWrapperDefault.getAllServerUrlDetailsOfCheckedEnv();
        EnvConfigBean envConfigFirstInstall = mEnvConfigWrapperDefault.getFirstInstall();
        EnvConfigBean envConfigLogDebug = mEnvConfigWrapperDefault.getLogDebug();
        EnvConfigBean envConfigSkipAdPage = mEnvConfigWrapperDefault.getSkipAdPage();
        String modeValueLast = allServerUrlDetailsOfCheckedEnv.getModeOfEnv();
        for (EnvConfigBean envConfigBean : envConfigBeanList) {
            String groupId = envConfigBean.getGroupId();
            switch (groupId) {
                case GROUP_ID_SERVER_URL_DETAILS:
                    if (envConfigBean instanceof AllServerUrlDetailsBean) {
                        AllServerUrlDetailsBean allServerUrlDetailsBean = (AllServerUrlDetailsBean) envConfigBean;
                        String modeValue = allServerUrlDetailsBean.getModeOfEnv();
                        if (TextUtils.equals(modeValueLast, modeValue)) {
                            envConfigBean.setChecked(CHECKED);
                        } else {
                            envConfigBean.setChecked(UNCHECKED);
                        }
                    } else {
                        LogUtils.el(TAG, "method:initEnvConfigListDataAndViews#envConfigBean not a instance of AllServerUrlDetailsBean.");
                    }
                    break;
                case GROUP_ID_FIRST_INSTALL:
                    if (envConfigFirstInstall != null) {
                        envConfigBean.setChecked(envConfigBean.getChecked());
                    }
                    break;
                case GROUP_ID_LOG_DEBUG:
                    if (envConfigLogDebug != null) {
                        envConfigBean.setChecked(envConfigLogDebug.getChecked());
                    }
                    break;
                case GROUP_ID_SKIP_AD_PAGE:
                    if (envConfigSkipAdPage != null) {
                        envConfigBean.setChecked(envConfigSkipAdPage.getChecked());
                    }
                    break;
                default:
                    LogUtils.el(TAG, "method:initEnvConfigListData#未处理当前逻辑分支");
                    break;
            }
        }

        ServerUrlDetailsBean apiDetailsInput = mEnvConfigWrapperDefault.getApiServerUrlDetailsInput();
        if (apiDetailsInput != null) {
            mUrlInputLayoutApi.setChecked(apiDetailsInput.isChecked());
            mUrlInputLayoutApi.setUrlInput(apiDetailsInput.getUrlHistoryBean());
        }
        ServerUrlDetailsBean imageDetailsInput = mEnvConfigWrapperDefault.getImageServerUrlDetailsInput();
        if (imageDetailsInput != null) {
            mUrlInputLayoutImage.setChecked(imageDetailsInput.isChecked());
            mUrlInputLayoutImage.setUrlInput(imageDetailsInput.getUrlHistoryBean());
        }
        ServerUrlDetailsBean h5DetailsInput = mEnvConfigWrapperDefault.getH5ServerUrlDetailsInput();
        if (h5DetailsInput != null) {
            mUrlInputLayoutH5.setChecked(h5DetailsInput.isChecked());
            mUrlInputLayoutH5.setUrlInput(h5DetailsInput.getUrlHistoryBean());
        }
    }

    private void handleInitEnvConfigListDataAndViews(List<EnvConfigBean> envConfigBeanList) {
        AppInfoBean appInfoBean = EnvConfigHelper.getInstance().getAppInfoBean();
        if (appInfoBean == null) {
            Toast.makeText(mContext, "appInfoBean = null", Toast.LENGTH_LONG).show();
            return;
        }
        String modeOfBuild = appInfoBean.getModeOfBuild();
        if (TextUtils.isEmpty(modeOfBuild)) {
            Toast.makeText(mContext, "modeOfBuild 为空", Toast.LENGTH_LONG).show();
            return;
        }
//        String modeBuild = BuildConfig.MODE;
        for (EnvConfigBean envConfigBean : envConfigBeanList) {
            String groupId = envConfigBean.getGroupId();
            switch (groupId) {
                case GROUP_ID_SERVER_URL_DETAILS:
                    if (envConfigBean instanceof AllServerUrlDetailsBean) {
                        handServerUrlDetalsDefault(modeOfBuild, envConfigBean);
                    } else {
                        LogUtils.el(TAG, "method:initEnvConfigListDataAndViews#envConfigBean not a instance of AllServerUrlDetailsBean.");
                    }
                    break;
                case GROUP_ID_FIRST_INSTALL:
                case GROUP_ID_LOG_DEBUG:
                case GROUP_ID_SKIP_AD_PAGE:
                    // 暂时按默认状态处理;
//                        String modePilotRun = EnvConfigHelper.EnvMode.DEV_PILOT_RUN.getMode();
//                        if (TextUtils.equals(modeBuild, modePilotRun) ||
//                                TextUtils.equals(modeBuild, modeDevPilotRun)) {
//                            envConfigBean.setChecked(CHECKED);
//                        } else {
//                            envConfigBean.setChecked(UNCHECKED);
//                        }
                    break;
                default:
                    LogUtils.el(TAG, "method:initEnvConfigListData#未处理当前逻辑分支");
                    break;
            }
        }
    }

    private void handServerUrlDetalsDefault(String modeBuild, EnvConfigBean envConfigBean) {
        AllServerUrlDetailsBean allServerUrlDetailsBean = (AllServerUrlDetailsBean) envConfigBean;
        String modeValue = allServerUrlDetailsBean.getModeOfEnv();
        if (TextUtils.equals(modeBuild, EnvConfigHelper.EnvMode.DEVELOPMENT.getMode())) {
            // 开发环境默认使用 DEV_TEST_SERVER;
            String modeDevServer = EnvConfigHelper.EnvMode.DEV_TEST_SERVER.getMode();
            if (TextUtils.equals(modeValue, modeDevServer)) {
                envConfigBean.setChecked(CHECKED);
            } else {
                envConfigBean.setChecked(UNCHECKED);
            }
        } else if (TextUtils.equals(modeBuild, EnvConfigHelper.EnvMode.PILOT_RUN.getMode())) {
            // 试运行环境默认使用 DEV_PILOT_RUN;
            String modeDevServer = EnvConfigHelper.EnvMode.DEV_PILOT_RUN.getMode();
            if (TextUtils.equals(modeValue, modeDevServer)) {
                envConfigBean.setChecked(CHECKED);
            } else {
                envConfigBean.setChecked(UNCHECKED);
            }
        } else if (TextUtils.equals(modeBuild, EnvConfigHelper.EnvMode.PRODUCT.getMode())) {
            // 生产环境默认使用 DEV_PRODUCT;
            String modeDevServer = EnvConfigHelper.EnvMode.DEV_PRODUCT.getMode();
            if (TextUtils.equals(modeValue, modeDevServer)) {
                envConfigBean.setChecked(CHECKED);
            } else {
                envConfigBean.setChecked(UNCHECKED);
            }
        }
    }

    /**
     * 根据点击事件发生所在position,及数据类型,修改了数据集合中相关数据的状态;
     *
     * @param position
     */
    private void updateListData(int position, EnvConfigBean evnConfigBean) {
        LogUtils.d(TAG, "method:updateListData#evnConfigBean=" + evnConfigBean);
        boolean isGroup = evnConfigBean.isGroup();
        if (isGroup) {
            // 多个选项为一组时的业务处理
            handleGroupSingleChecked(position, evnConfigBean);
        } else {
            boolean isChecked = evnConfigBean.isChecked();
            // 单个选项为一组时的业务处理
//            switch (groupId) {
//                case GROUP_ID_SKIP_AD_PAGE:
//                case GROUP_ID_FIRST_INSTALL:
//                case GROUP_ID_LOG_DEBUG:
            evnConfigBean.setChecked(!isChecked);
//                    break;
//                default:
//                    LogUtils.el(TAG, "method:updateListData#未处理当前逻辑分支");
//                    break;
//            }
        }
    }

    /**
     * 处理一组内容选中的逻辑,单选逻辑;
     * 如果是必选项,则只有一个可被选中,否则可以没有选中项;
     *
     * @param position
     * @param evnConfigBean
     */
    private void handleGroupSingleChecked(int position, EnvConfigBean evnConfigBean) {
        String groupIdChecked = evnConfigBean.getGroupId();
        boolean isRequired = evnConfigBean.isRequired();
        boolean isChecked = evnConfigBean.isChecked();
        for (int i = 0; i < mEnvConfigList.size(); i++) {
            EnvConfigBean item = mEnvConfigList.get(i);
            String groupIdItem = item.getGroupId();
            if (!TextUtils.equals(groupIdChecked, groupIdItem)) {
                continue;
            }
            // 保证同一组内的选项有且只有一个可被选中;
            if (position == i) {
                if (isRequired) {
                    if (isChecked) {
                        LogUtils.wl(TAG, "method:handleGroupSingleChecked#isRequired=" + isRequired
                                + ", isChecked=" + isChecked);
                    } else {
                        // 保证同一组内的选项至少有一个选项被选中;
                        evnConfigBean.setChecked(!isChecked);
                    }
                } else {
                    evnConfigBean.setChecked(!isChecked);
                }
            } else {
                item.setChecked(UNCHECKED);
            }
        }
    }

    /**
     * 处理点击完成的业务;
     */
    private void handlerFinishClicked() {
        EnvConfigWrapper envConfigWrapper = buildEnvConfigWrapper();
        // 暂时使用 SharedPreferences 作为本地缓存,根据实际需要选择处理方式;
        Gson gson = new Gson();
        String envConfigWrapperJson = gson.toJson(envConfigWrapper);
        SharedPrefsManager.getInstance()
                .init(mContext, Consts.ENV_CONFIG.ENV_CONFIG_SP)
                .putString(Consts.ENV_CONFIG.ENV_CONFIG_WRAPPER_JSON, envConfigWrapperJson)
                .commit();
        // 修改环境配置的方法可以根据需求放在 EnvConfigDialogFragment 的此处调用;
        // 也可以在页面的 mEnvConfigCheckedCompleteListener 回调时调用;
//        EnvConfigHelper.getInstance()
//                .updateEnvServerUrl(envConfigWrapper.getAllServerUrlDetailsOfCheckedEnv().getModeOfEnv(), envConfigWrapper);
        // 接口回调;
        if (mEnvConfigCheckedCompleteListener == null) {
            LogUtils.el(TAG, "method:handlerFinishClicked#mConfigCompleteListener = " + mEnvConfigCheckedCompleteListener);
        } else {
            mEnvConfigCheckedCompleteListener.onEnvConfigCheckedComplete(envConfigWrapper);
        }
        dismiss();
    }

    /**
     * 构建返回结果,将选中的数据内容封装在对象内;
     *
     * @return
     */
    private EnvConfigWrapper buildEnvConfigWrapper() {
        EnvConfigWrapper envConfigWrapper = new EnvConfigWrapper();
        for (int i = 0; i < mEnvConfigList.size(); i++) {
            EnvConfigBean item = mEnvConfigList.get(i);
            String groupIdItem = item.getGroupId();
            switch (groupIdItem) {
                // 封装当前选项的数据
                case GROUP_ID_SKIP_AD_PAGE:
                    envConfigWrapper.setSkipAdPage((EnvConfigBean) item.clone());
                    break;
                // 封装当前选项的数据
                case GROUP_ID_FIRST_INSTALL:
                    envConfigWrapper.setFirstInstall((EnvConfigBean) item.clone());
                    break;
                // 封装当前选项的数据
                case GROUP_ID_LOG_DEBUG:
                    envConfigWrapper.setLogDebug((EnvConfigBean) item.clone());
                    break;
                // 封装当前选项的数据
                case GROUP_ID_SERVER_URL_DETAILS:
                    if (!item.getChecked()) {
                        continue;
                    }
                    if (item instanceof AllServerUrlDetailsBean) {
                        AllServerUrlDetailsBean serverUrlDetailsBean = (AllServerUrlDetailsBean) item;
                        envConfigWrapper.setAllServerUrlDetailsOfCheckedEnv((AllServerUrlDetailsBean) serverUrlDetailsBean.clone());
                    } else {
                        LogUtils.el(TAG, "method:handlerFinishClicked#envConfigBean not a instance of AllServerUrlDetailsBean.");
                    }
                    break;
                default:
                    LogUtils.el(TAG, "method:handlerFinishClicked#未处理当前逻辑分支");
                    break;
            }
        }

        UrlHistoryBean urlInputApi = null;
        UrlHistoryBean urlInputImage = null;
        UrlHistoryBean urlInputH5 = null;
        if (mUrlInputLayoutApi != null && mUrlInputLayoutApi.isChecked()) {
            ServerUrlDetailsBean urlDetailApi = mUrlInputLayoutApi.getUrlDetailBean();
            if (urlDetailApi == null) {
                Toast.makeText(mContext, mUrlInputLayoutApi.getTypeName() + "输入的URL地址无效", Toast.LENGTH_SHORT).show();
            } else {
                envConfigWrapper.setApiServerUrlDetailsInput(urlDetailApi);
                urlInputApi = urlDetailApi.getUrlHistoryBean();
            }
        }
        if (mUrlInputLayoutImage != null && mUrlInputLayoutImage.isChecked()) {
            ServerUrlDetailsBean urlDetailImage = mUrlInputLayoutImage.getUrlDetailBean();
            if (urlDetailImage == null) {
                Toast.makeText(mContext, mUrlInputLayoutImage.getTypeName() + "输入的URL地址无效", Toast.LENGTH_SHORT).show();
            } else {
                envConfigWrapper.setImageServerUrlDetailsInput(urlDetailImage);
                urlInputImage = urlDetailImage.getUrlHistoryBean();
            }
        }
        if (mUrlInputLayoutH5 != null && mUrlInputLayoutH5.isChecked()) {
            ServerUrlDetailsBean urlDetailH5 = mUrlInputLayoutH5.getUrlDetailBean();
            if (urlDetailH5 == null) {
                Toast.makeText(mContext, mUrlInputLayoutH5.getTypeName() + "输入的URL地址无效", Toast.LENGTH_SHORT).show();
            } else {
                envConfigWrapper.setH5ServerUrlDetailsInput(urlDetailH5);
                urlInputH5 = urlDetailH5.getUrlHistoryBean();
            }
        }
        if (urlInputApi != null || urlInputImage != null || urlInputH5 != null) {
            List<UrlHistoryBean> urllList = new ArrayList<>();
            addUrlInput(urlInputApi, urllList);
            addUrlInput(urlInputImage, urllList);
            addUrlInput(urlInputH5, urllList);
            EnvConfigHelper.getInstance().saveUrlInputHistory(urllList);
        }

        AppInfoBean appInfoBean = EnvConfigHelper.getInstance().getAppInfoBean();
        if (appInfoBean != null) {
            envConfigWrapper.setModeOfBuild(appInfoBean.getModeOfBuild());
        } else {
            LogUtils.el(TAG, "method:handlerFinishClicked#EnvConfigHelper#mAppInfoBean not initialize.");
        }
        return envConfigWrapper;
    }

    private void addUrlInput(UrlHistoryBean urlHistoryBean, List<UrlHistoryBean> urllList) {
        if (urlHistoryBean != null && !TextUtils.isEmpty(urlHistoryBean.getUrlStr())) {
            urllList.add(urlHistoryBean);
        }
    }

    @NonNull
    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        Dialog dialog = super.onCreateDialog(savedInstanceState);
        dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
        return dialog;
    }

}

??EnvConfigHelper 类的 saveUrlInputHistory() 缓存方法的业务重新实现,以实现历史列表的保存,及不重复等功能;

package com.windfallsheng.envconfig;

import android.content.Context;
import android.text.TextUtils;

import androidx.annotation.StringDef;

import com.google.gson.Gson;
import com.google.gson.JsonSyntaxException;
import com.google.gson.reflect.TypeToken;
import com.windfallsheng.envconfig.bean.AllServerUrlDetailsBean;
import com.windfallsheng.envconfig.bean.AppInfoBean;
import com.windfallsheng.envconfig.bean.EnvConfigWrapper;
import com.windfallsheng.envconfig.bean.ServerUrlDetailsBean;
import com.windfallsheng.envconfig.bean.UrlHistoryBean;
import com.windfallsheng.envconfig.dialog.EnvConfigDialogFragment;
import com.windfallsheng.lib.Consts;
import com.windfallsheng.lib.Consts.ENV_MODE;
import com.windfallsheng.lib.util.LogUtils;
import com.windfallsheng.lib.util.SharedPrefsManager;

import java.util.ArrayList;
import java.util.List;

/**
 * @Author: lzsheng
 * @CreateDate: 2020/12/17 15:22
 * @LastModifiedTime: 2020/12/17 15:22
 * @Description: 单例模式,以方便全局随时可以获取设置的参数;
 */
public class EnvConfigHelper {

    public static String TAG = "EnvConfigHelper";
    private Context mContext;
    private String mModeSelected;
    private AppInfoBean mAppInfoBean;

    private EnvConfigHelper() {
    }

    public static EnvConfigHelper getInstance() {
        return SingletonHolder.INSTANCE;
    }

    public EnvConfigHelper initContext(Context context) {
        mContext = context;
        return this;
    }

    public String getModeSelected() {
        return mModeSelected;
    }

    public AppInfoBean getAppInfoBean() {
        return mAppInfoBean;
    }

    public void setAppInfoBean(AppInfoBean appInfoBean) {
        mAppInfoBean = appInfoBean;
    }

    /**
     * 根据选择的环境类型,调整环境配置;
     *
     * @param modeValue
     */
    public void updateEnvServerUrl(@MODE String modeValue, EnvConfigWrapper envConfigWrapper) {
        // 修改当前模式为已修改的模式;
        this.mModeSelected = modeValue;
        // 判断是否有手动输入的地址项;
        String urlApiStr = "";
        String urlImageStr = "";
        String urlH5Str = "";
        if (envConfigWrapper != null) {
            ServerUrlDetailsBean apiDetailsInput = envConfigWrapper.getApiServerUrlDetailsInput();
            if (apiDetailsInput != null) {
                UrlHistoryBean urlHistoryBean = apiDetailsInput.getUrlHistoryBean();
                if (urlHistoryBean != null) {
                    urlApiStr = urlHistoryBean.getUrlStr();
                }
            }
            ServerUrlDetailsBean imageDetailsInput = envConfigWrapper.getImageServerUrlDetailsInput();
            if (imageDetailsInput != null) {
                UrlHistoryBean urlHistoryBean = imageDetailsInput.getUrlHistoryBean();
                if (urlHistoryBean != null) {
                    urlImageStr = urlHistoryBean.getUrlStr();
                }
            }
            ServerUrlDetailsBean h5DetailsInput = envConfigWrapper.getH5ServerUrlDetailsInput();
            if (h5DetailsInput != null) {
                UrlHistoryBean urlHistoryBean = h5DetailsInput.getUrlHistoryBean();
                if (urlHistoryBean != null) {
                    urlH5Str = urlHistoryBean.getUrlStr();
                }
            }
        }
        // 手动输入的地址项优先赋值;
        if (!TextUtils.isEmpty(urlApiStr)) {
            EnvServerUrlConsts.API_SERVER = urlApiStr;
        }
        if (!TextUtils.isEmpty(urlImageStr)) {
            EnvServerUrlConsts.IMAGE_SERVER = urlImageStr;
        }
        if (!TextUtils.isEmpty(urlH5Str)) {
            EnvServerUrlConsts.H5_SERVER = urlH5Str;
        }
        switch (modeValue) {
            case ENV_MODE.DEV_TEST_LOCAL:

                // 手动输入的地址项优先赋值,若没有输入地址,则使用默认配置地址;
                if (TextUtils.isEmpty(urlApiStr)) {
                    EnvServerUrlConsts.API_SERVER = EnvServerUrlConsts.TestLocal.API_SERVER;
                }
                if (TextUtils.isEmpty(urlImageStr)) {
                    EnvServerUrlConsts.IMAGE_SERVER = EnvServerUrlConsts.TestLocal.IMAGE_SERVER;
                }
                if (TextUtils.isEmpty(urlH5Str)) {
                    EnvServerUrlConsts.H5_SERVER = EnvServerUrlConsts.TestLocal.H5_SERVER;
                }
                break;
            case ENV_MODE.DEVELOPMENT:
            case ENV_MODE.DEV_TEST_SERVER:
                // 手动输入的地址项优先赋值,若没有输入地址,则使用默认配置地址;
                if (TextUtils.isEmpty(urlApiStr)) {
                    EnvServerUrlConsts.API_SERVER = EnvServerUrlConsts.TestServer.API_SERVER;
                }
                if (TextUtils.isEmpty(urlImageStr)) {
                    EnvServerUrlConsts.IMAGE_SERVER = EnvServerUrlConsts.TestServer.IMAGE_SERVER;
                }
                if (TextUtils.isEmpty(urlH5Str)) {
                    EnvServerUrlConsts.H5_SERVER = EnvServerUrlConsts.TestServer.H5_SERVER;
                }
                break;
            case ENV_MODE.PILOT_RUN:
            case ENV_MODE.DEV_PILOT_RUN:
                // 手动输入的地址项优先赋值,若没有输入地址,则使用默认配置地址;
                if (TextUtils.isEmpty(urlApiStr)) {
                    EnvServerUrlConsts.API_SERVER = EnvServerUrlConsts.PilotRun.API_SERVER;
                }
                if (TextUtils.isEmpty(urlImageStr)) {
                    EnvServerUrlConsts.IMAGE_SERVER = EnvServerUrlConsts.PilotRun.IMAGE_SERVER;
                }
                if (TextUtils.isEmpty(urlH5Str)) {
                    EnvServerUrlConsts.H5_SERVER = EnvServerUrlConsts.PilotRun.H5_SERVER;
                }
                break;
            case ENV_MODE.PRODUCT:
            case ENV_MODE.DEV_PRODUCT:
                // 手动输入的地址项优先赋值,若没有输入地址,则使用默认配置地址;
                if (TextUtils.isEmpty(urlApiStr)) {
                    EnvServerUrlConsts.API_SERVER = EnvServerUrlConsts.Product.API_SERVER;
                }
                if (TextUtils.isEmpty(urlImageStr)) {
                    EnvServerUrlConsts.IMAGE_SERVER = EnvServerUrlConsts.Product.IMAGE_SERVER;
                }
                if (TextUtils.isEmpty(urlH5Str)) {
                    EnvServerUrlConsts.H5_SERVER = EnvServerUrlConsts.Product.H5_SERVER;
                }
                break;
            default:
                LogUtils.el(TAG, "method:updateEnvServerUrl#未处理当前逻辑分支");
                break;
        }

        LogUtils.dl("updateEnvServerUrl★★\n★★modeValue=" + modeValue +
                "\n★★EnvServerUrlConsts.API_SERVER=" + EnvServerUrlConsts.API_SERVER +
                ", \n★★EnvServerUrlConsts.IMAGE_SERVER=" + EnvServerUrlConsts.IMAGE_SERVER +
                ", \n★★EnvServerUrlConsts.H5_SERVER=" + EnvServerUrlConsts.H5_SERVER);
    }

    /**
     * 根据选择的环境类型,调整环境配置;
     *
     * @param envConfigWrapper
     */
    public void updateEnvServerUrl(EnvConfigWrapper envConfigWrapper) {
        if (envConfigWrapper == null) {
            LogUtils.el(TAG, "method:updateEnvServerUrl#return#envConfigWrapper == null");
            return;
        }
        AllServerUrlDetailsBean allServerUrlDetailsOfCheckedEnv = envConfigWrapper.getAllServerUrlDetailsOfCheckedEnv();
        if (allServerUrlDetailsOfCheckedEnv == null) {
            LogUtils.el(TAG, "method:updateEnvServerUrl#return#allServerUrlDetailsOfCheckedEnv == null");
            return;
        }
        String modeValue = allServerUrlDetailsOfCheckedEnv.getModeOfEnv();
        updateEnvServerUrl(modeValue, envConfigWrapper);
    }

    /**
     * 根据选择的环境类型,调整环境配置;
     *
     * @param modeValue
     */
    public void updateEnvServerUrl(@MODE String modeValue) {
        updateEnvServerUrl(modeValue, null);
    }

    /**
     * 在应用启动时最先初始化配置信息;
     */
    public void initDefaultEnv() {
        String modeValue = null;
        LogUtils.dl(TAG, "method:initDefaultEnv#mAppInfoBean=" + mAppInfoBean);
        if (mAppInfoBean == null) {
            LogUtils.el(TAG, "method:initDefaultEnv#return#mAppInfoBean == null");
            return;
        }

        modeValue = mAppInfoBean.getModeOfBuild();
        LogUtils.dl(TAG, "method:initDefaultEnv#modeValue=" + modeValue);

        if (TextUtils.isEmpty(modeValue)) {
            LogUtils.el(TAG, "method:initDefaultEnv#return#modeValue == " + modeValue);
            return;
        }
        // 如果打包构建的环境是生产和试运行,则以打包环境为准
        if (TextUtils.equals(modeValue, ENV_MODE.PILOT_RUN) ||
                TextUtils.equals(modeValue, ENV_MODE.PRODUCT)) {
            updateEnvServerUrl(modeValue);
        } else if (TextUtils.equals(modeValue, ENV_MODE.DEVELOPMENT)) {
            // 如果是开发环境,先检查是否有上次缓存的配置数据;
            EnvConfigWrapper envConfigWrapper = initEnvConfigWrapper();
            LogUtils.dl(TAG, "method:initDefaultEnv#envConfigWrapper=" + envConfigWrapper);
            if (envConfigWrapper == null) {
                // 如果没有缓存数据,则以构建环境为准;
                modeValue = mAppInfoBean.getModeOfBuild();
                updateEnvServerUrl(modeValue);
            } else {
                // 如果上次缓存的有数据,则以缓存数据为准;
                updateEnvServerUrl(envConfigWrapper);
            }
        }
    }

    public EnvConfigWrapper initEnvConfigWrapper() {
        if (mContext == null) {
            LogUtils.el(TAG, "method:initEnvConfigWrapper#return null#mContext == null");
            return null;
        }
        // 暂时使用 SharedPreferences 作为本地缓存,根据实际需要选择处理方式;
        String envConfigWrapperJson = SharedPrefsManager.getInstance()
                .init(mContext, Consts.ENV_CONFIG.ENV_CONFIG_SP)
                .getString(Consts.ENV_CONFIG.ENV_CONFIG_WRAPPER_JSON, "");
        EnvConfigWrapper envConfigWrapper = null;
        if (!TextUtils.isEmpty(envConfigWrapperJson)) {
            Gson gson = new Gson();
            try {
                envConfigWrapper = gson.fromJson(envConfigWrapperJson, EnvConfigWrapper.class);
            } catch (JsonSyntaxException e) {
                LogUtils.el(TAG, "method:initEnvConfigWrapper#e=" + e.getMessage());
                SharedPrefsManager.getInstance()
                        .init(mContext, Consts.ENV_CONFIG.ENV_CONFIG_SP)
                        .removeKey(Consts.ENV_CONFIG.ENV_CONFIG_WRAPPER_JSON);
            }
        }
        return envConfigWrapper;
    }

    public void saveUrlInputHistory(List<UrlHistoryBean> urlStrInputList) {
        if (urlStrInputList == null || urlStrInputList.size() == 0) {
            return;
        }
        //  默认类型的URL不需要再缓存,可以移除;
        int size = urlStrInputList.size();
        for (int i = 0; i < size; i++) {
            UrlHistoryBean urlInputBean = urlStrInputList.get(i);
            String typeInput = urlInputBean.getType();
            // 如果输入的是默认的地址,则从输入列表中移除,这样能保证默认的地址不在新增的历史记录里;
            if (TextUtils.equals(typeInput, EnvConfigDialogFragment.URL_HISTORY_TYPE_DEFAULT)) {
                urlStrInputList.remove(urlInputBean);
                i--;
                size--;
            }
        }
        int sizeNew = urlStrInputList.size();
        // 移除内部URL字段相同的重复元素;
        if (sizeNew > 1) {
            for (int i = 0; i < sizeNew; i++) {
//                if (sizeNew <= 1) {
//                    break;
//                }
                UrlHistoryBean urlInputBean = urlStrInputList.get(i);
                String url = urlInputBean.getUrlStr();
                for (int j = i + 1; j < sizeNew; j++) {
                    UrlHistoryBean next = urlStrInputList.get(j);
                    String urlNext = next.getUrlStr();
                    // 移除内部URL字段相同的重复元素;
                    if (TextUtils.equals(url, urlNext)) {
                        urlStrInputList.remove(next);
                        j--;
                        sizeNew--;
                    }
                }
            }
        }

        Gson gson = new Gson();
        // 查看是否有缓存;
        SharedPrefsManager sharedPrefsManager = SharedPrefsManager.getInstance()
                .init(mContext, Consts.ENV_CONFIG.ENV_CONFIG_SP);
        String json = sharedPrefsManager
                .getString(Consts.ENV_CONFIG.URL_INPUT_HISTORY_JSON);
        List<UrlHistoryBean> historyList = null;
        if (!TextUtils.isEmpty(json)) {
            try {
                historyList = gson.fromJson(json, new TypeToken<List<UrlHistoryBean>>() {
                }.getType());
            } catch (JsonSyntaxException e) {
                LogUtils.el(TAG, "method:initEnvConfigWrapper#e=" + e.getMessage());
                sharedPrefsManager
                        .removeKey(Consts.ENV_CONFIG.URL_INPUT_HISTORY_JSON);
            }
            if (historyList != null) {
                //  限制缓存数量;
                for (; ; ) {
                    if (historyList.size() > 50) {
                        historyList.remove(historyList.size() - 1);
                    } else {
                        break;
                    }
                }
                //  移除新输入的地址和缓存中重复元素
                int sizeInput = urlStrInputList.size();
                for (int i = 0; i < sizeInput; i++) {
                    int sizeHistory = historyList.size();
                    UrlHistoryBean urlInputBean = urlStrInputList.get(i);
                    String urlInput = urlInputBean.getUrlStr();
                    String typeInput = urlInputBean.getType();
                    // 如果输入的是默认的地址,则从输入列表中移除,这样能保证默认的地址不在新增的历史记录里;
                    if (TextUtils.equals(typeInput, EnvConfigDialogFragment.URL_HISTORY_TYPE_DEFAULT)) {
                        urlStrInputList.remove(urlInputBean);
                        i--;
                        sizeInput--;
                    }

                    // 如果输入的地址和历史中的记录重复时;
                    for (int j = 0; j < sizeHistory; j++) {
                        UrlHistoryBean item = historyList.get(j);
                        String urlHistory = item.getUrlStr();
                        if (TextUtils.equals(urlInput, urlHistory)) {
                            // 移除原历史列表中的相同地址和记录;
                            historyList.remove(item);
                            j--;
                            sizeHistory--;
                        }
                    }
                }
            }
        }
        if (historyList == null) {
            historyList = new ArrayList<>();
        }
        historyList.addAll(0, urlStrInputList);
        if (historyList.size() > 0) {
            String newJson = gson.toJson(historyList);
            sharedPrefsManager
                    .putString(Consts.ENV_CONFIG.URL_INPUT_HISTORY_JSON, newJson)
                    .commit();
        }

    }

    /**
     * 自定义的环境模式,其属性值如果在productFlavors中存在则要和它保持一致;
     */
    public enum EnvMode {
        /**
         * 开发版本下的服务器测试环境
         */
        DEV_TEST_SERVER(ENV_MODE.DEV_TEST_SERVER),
        /**
         * 开发版本下的本地环境
         */
        DEV_TEST_LOCAL(ENV_MODE.DEV_TEST_LOCAL),
        /**
         * 开发版本下的试运行环境
         */
        DEV_PILOT_RUN(ENV_MODE.DEV_PILOT_RUN),
        /**
         * 开发版本下的生产环境
         */
        DEV_PRODUCT(ENV_MODE.DEV_PRODUCT),
        /**
         * 开发版本
         */
        DEVELOPMENT(ENV_MODE.DEVELOPMENT),
        /**
         * 试运行版本
         */
        PILOT_RUN(ENV_MODE.PILOT_RUN),
        /**
         * 生产版本
         */
        PRODUCT(Consts.ENV_MODE.PRODUCT);

        private String mMode;

        EnvMode(String mode) {
            this.mMode = mode;
        }

        public String getMode() {
            return mMode;
        }
    }

    @StringDef({ENV_MODE.DEV_TEST_LOCAL, ENV_MODE.DEV_TEST_SERVER, ENV_MODE.DEV_PILOT_RUN, ENV_MODE.DEV_PRODUCT, ENV_MODE.DEVELOPMENT, ENV_MODE.PILOT_RUN, ENV_MODE.PRODUCT})
    public @interface MODE {
    }

    private static class SingletonHolder {
        private static final EnvConfigHelper INSTANCE = new EnvConfigHelper();
    }

}

总结

??在原来的业务大框架下,新增了手动输入的URL的历史记录的功能,基本是满足大部分使用场景的,实际应用还要立足于自身项目,做一些调整。

  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2021-08-14 14:11:29  更:2021-08-14 14:13:39 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/18 22:06:26-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码