Android在debug和release模式自动加载不同的配置文件

思路:
1. 判断当前运行在何种模式下
2. 加载配置文件

1. 判断当前运行在何种模式下

当直接在eclipse中运行程序和android tools工具打包时候,会自动修改gen/**/BuildConfig.java中的字段DEBUG字段的值

if (BuildConfig.DEBUG) {
    // debug模式
} else {
    // release模式
}

2. 加载配置文件

使用PULL解析器解析asset中的不同配置文件,每个配置文件配置了需要反射的类名称信息以及字段信息

xml文件格式:

<?xml version="1.0" encoding="UTF-8"?>
<root>
    <description></description>
    <className>com.yanjun.testpowerful.Config</className>
    <a>1</a>
    <b>2</b>
</root>

解析类:

package com.yanjun.testpowerful.util;

import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.HashMap;
import java.util.Map;

import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;

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

public class LoadConfigUtil {

    // 解析对应到类
    private static final String TAG_CLASSNAME = "className";

    // xml中根节点tag名称
    private static final String TAG_ROOTNAME = "root";

    // xml编码
    private static final String XML_ENCODING = "utf-8";

    /**
     * 加载配置
     * @param ctx
     * @param fileName
     * @throws IOException
     * @throws XmlPullParserException
     */
    public static void load(Context ctx, String fileName) throws IOException, XmlPullParserException {
        // 将xml解析为map
        Map<String, String> content = parser(ctx, fileName);

        // 检查类配置
        String className = content.get(TAG_CLASSNAME);
        if (TextUtils.isEmpty(className)) {
            throw new IllegalStateException("missing configuration: missing " + TAG_CLASSNAME);
        }

        Class<?> clazz;
        try {
            clazz = Class.forName(className);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
            return ;
        }

        // 通过反射设置值
        Field[] fields = clazz.getDeclaredFields();
        for (Field field : fields) {
            try {
                // 只反射静态字段
                if ((field.getModifiers() & Modifier.STATIC) != Modifier.STATIC) {
                    continue ;
                }

                String fieldName = field.getName();
                if (!content.containsKey(fieldName)) {
                    continue;
                }

                field.setAccessible(true);
                field.set(null, content.get(fieldName));
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    /*
     * 将xml解析为map
     */
    private static Map<String, String> parser(Context ctx, String fileName) throws IOException, XmlPullParserException {
        Map<String, String> content = new HashMap<String, String>();

        InputStream in = ctx.getAssets().open(fileName);
        try {
            XmlPullParser parser = Xml.newPullParser();
            parser.setInput(in, XML_ENCODING);

            String lastTagName = null;
            int eventType = parser.getEventType();
            while (eventType != XmlPullParser.END_DOCUMENT) {
                switch (eventType) {
                case XmlPullParser.START_DOCUMENT:
                    break;
                case XmlPullParser.START_TAG:
                    if (parser.getName().equals(TAG_ROOTNAME)) {
                        break;
                    }

                    lastTagName = parser.getName();

                    break;
                case XmlPullParser.TEXT:
                    if (lastTagName == null) {
                        break;
                    }

                    String value = parser.getText();
                    if (value != null) {
                        content.put(lastTagName, value.trim());
                    }
                case XmlPullParser.END_TAG:
                    lastTagName = null;

                    break;
                }

                eventType = parser.next();
            }
        } finally {
            if (in != null) {
                in.close();
            }
        }

        return content;
    }

}

在Application创建的时候反射具体的配置到类中:

package com.yanjun.testpowerful;

import android.app.Application;

import com.yanjun.testpowerful.util.LoadConfigUtil;

public class MyApplication extends Application {

    @Override
    public void onCreate() {
        super.onCreate();

        // 加载配置文件
        loadConfig();
    }

    /*
     * 加载配置文件
     */
    private void loadConfig() {
        try {
            if (BuildConfig.DEBUG) {
                LoadConfigUtil.load(this, "config-debug.xml");
            } else {
                LoadConfigUtil.load(this, "config-release.xml");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}

后续:

优点

-可以对生产环境和测试环境使用两套不同的配置,并动态切换,不用修改代码和配置

缺点
-在app启动的时候使用到了解析xml、反射等技术,可能会额外增加app启动时间,尤其在配置较多的时候
提示
-减少不必要的配置
-将必须的配置定义到同一个类中,其它常量定义其他类中
-如果使用了混淆,记得去掉混淆xml中配置的类
-如果需要动态加载多个类的配置,可使用多个配置文件

补充:

当引用Library项目时,使用了Library项目中的BuildConfig类,该类中的DEBUG不会在打包的时候被修改,可以Application启动的时候通过代码获取程序的模式,并做相应的设置

// 判断是否是以debug模式运行
if ((getApplicationInfo().flags & ApplicationInfo.FLAG_DEBUGGABLE) == ApplicationInfo.FLAG_DEBUGGABLE) {
    // 设置日志输出级别:输出所有日志
    LOG_LEVEL = LOG_LEVEL_DEBUG|LOG_LEVEL_INFO|LOG_LEVEL_WARN|LOG_LEVEL_ERROR|LOG_LEVEL_ASSERT;
} else {
    // 设置日志输出级别:不输出
    LOG_LEVEL = 0;
}
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值