在实际的开发工程中,一般会遇到开发环境测试环境,预发布环境,线上测试环境,线上环境多种环境互相切换的问题,而跟后台进行本地调试接口,又会加入其他的不可预料的环境配置,抛开用变量做环境配置的不说。下面就我遇到的几个问题及解决方式,做个总结,看官按需选择:

1.android studio中的bildcofig的环境编译配置,在编译的过程中,就会把gradle中的配置,生成一个buildcofig的类。

build.gradle的配置:

buildTypes {
    DT1 {
        buildConfigField 'String', 'SOCKETIO_URL', '"http://192.168.6.76:19082"'
    }
    DT2 {
        buildConfigField 'String', 'SOCKETIO_URL', '"http://192.168.6.76:19082"'
    }
}

在build工程之前选择下相应的环境:



在编译过后会生成一个类:


在url配置中,加入的buildconfig.base就是当前的环境配置。

该种方式,官方支持,但是在每次的build之前需要进行选择,不能在打包之后进行自由配置。


2.使用文件来构成环境选择的base配置。(例如sp,xml等等方式)

存在问题:从文件读出base环境之后,如果urlconstant中的配置是以static来进行的组装,那么会产生刷新不了static量的问题,如果是在使用中自行组装是没问题的。


3.使用urlconstant同时希望用static来事先组织好完整url的情况,就需要在用户打包好apk的时候用选择栏进行动态切换环境的情况。

那么我们需要多做一层操作:

import android.util.Log;

import java.lang.reflect.Field;
import java.util.LinkedList;
import java.util.List;
public class reject_utls {

    public static void reject(Object model){
        String baseUrl = "BaseUrl";
        List <String > allBase = new LinkedList<>();

        Field[] fields = model.getClass().getDeclaredFields(); // 获取实体类的所有属性,返回Field数组
        try {
            for (int j = 0; j < fields.length; j++) { // 遍历所有属性
                String name = fields[j].getName(); // 获取属性的名字
                name = name.substring(0, 1).toUpperCase() + name.substring(1);
                String type = fields[j].getGenericType().toString(); // 获取属性的类型
                if (type.equals("class java.lang.String")) { // 如果type是类类型,则前面包含"class ",后面跟类名

                    if(judgeContain(name)){//不处理
                        Field field = fields[j];
                        String value  = field.get(null).toString();
                        allBase.add(value);
                    }else{
                        Log.e("text",""+ name);
                        Field field = fields[j];
                        //将字段的访问权限设为true:即去除private修饰符的影响
                        field.setAccessible(true);
//                        /*去除final修饰符的影响,将字段设为可修改的*/
//                        Field modifiersField = Field.class.getDeclaredField("modifiers");
//                        modifiersField.setAccessible(true);
//                        modifiersField.set(field, field.getModifiers() & ~Modifier.FINAL);
                        String value  = field.get(null).toString();
                        //把字段值设置为自己的值
//                        field.set(null, Constant.BaseUrl + value.replace(baseUrl,""));
                    }

                }

            }
        } catch (SecurityException e) {
            e.printStackTrace();
            Log.e("text",""+ e.getStackTrace());
        } catch (IllegalAccessException e) {
            e.printStackTrace();
            Log.e("text",""+ e.getStackTrace());
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
            Log.e("text",""+ e.getStackTrace());
        }
    }
    //加入自己例外处理的base的那么
    public static boolean judgeContain(String name){
        String [] array = new String[]{"SOCKETIO_URL","UPLOAD_PIC","SALES","BASE","TRANSPORTION","WAREHOUSE","LABOR","SUPPLY","DATASYNC","H5"};
        for(String dest: array){
            if(name.contains(dest)){
                return true;
            }
        }
        return false;
    }
}

在这里使用反射,在选择了baseurl之后,动态的将所有的static的属性都刷新一边,原因在于urlconstant的管理是如下的:

public static String url1 = SOCKETIO_URL1 + "/getInfo5";
public static String url2 = UPLOAD_PIC1 + "/getInfo5";
public static String url3 = SALES1 + "/getInfo5";

及时每次选择了base之后,的SOCKETIO_URL变了,但是因为是static类型,不会再次到url的拼接操作中,那么最终的url1,url2,url3都不会实时的变化。故需要加入一个反射刷新的操作。

同时在第二种文件方式中,若url也是拼接之后直接使用的话,也可以用上述的方式,进行刷新属性值的操作,来实现动态切换环境。

当然,客官使用了变量的方式来处理的话,另说不会有太多问题,或者在每次获取url的时候用方法在中间进行组装的话,因为会每次走一次拼接的操作,所以也不存在太多的问题。