仅在调试版本变体中包含 Stetho
Include Stetho only in the debug build variant
我知道我可以使用 debugCompile
只为 debug build
拉入 dependency
。是否有一种好的、简化的方法来完成所需的 code initialization
?没有依赖项,其他变体将无法编译。
你有几个选择。
选项 1: 为所有构建包含 Stetho(使用 compile
而不是 debugCompile
)并且仅在 Application
class 用于调试版本。
这很容易做到。在你的 Application
class 中,像这样检查 BuildConfig.DEBUG
:
if (BuildConfig.DEBUG) {
Stetho.initialize(
Stetho.newInitializerBuilder(this)
.enableDumpapp(Stetho.defaultDumperPluginsProvider(this))
.enableWebKitInspector(Stetho.defaultInspectorModulesProvider(this))
.build()
);
}
选项 2: 仅包括用于调试版本的 Stetho,并为调试和发布版本创建不同的 Application
classes。
感谢 Gradle,应用程序可以针对不同的构建变体使用不同的源集。默认情况下,您有发布和调试构建类型,因此您可以拥有三个不同的源集:
- 调试 只需要在调试版本中使用的代码
- release 只需要发布版本中的代码
- main 所有构建中你想要的代码
您的应用程序代码目前可能全部在 main
源集中。您可以简单地在应用程序中的 main
文件夹旁边创建一个名为 debug
的新文件夹,并为要为调试构建添加的所有内容镜像 main
文件夹的结构。
在这种情况下,您希望 main
源集中的 Application
class 根本不引用 Stetho。
那么您需要 Application
class 在您的 debug
源集中像往常一样初始化 Stetho。
您可以在 Stetho sample. Specifically, here's the main Application class, and here's the debug Application class 中看到此设置的示例。另请注意,他们在每个源集中设置清单,选择要使用的应用程序 class。
查看@Tanis 的回答。
你也可以这样使用:
仅在 调试版本 上添加库。
dependencies {
debugCompile 'com.facebook.stetho:stetho:1.1.1
}
在您的应用程序中,您可以执行以下操作:
public class ExampleApplication extends Application {
@Override public void onCreate() {
super.onCreate();
StethoUtils.install(this);
}
}
然后你可以在debug/release版本中创建不同的StethoUtils
class。
在src/debug/java/
public class StethoUtils{
public static void install(Application application){
Stetho.initialize(
Stetho.newInitializerBuilder(application)
.enableDumpapp(Stetho.defaultDumperPluginsProvider(application))
.enableWebKitInspector(Stetho.defaultInspectorModulesProvider(application))
.build());
}
}
在src/release/java/
public class StethoUtils{
public static void install(Application application){
// do nothing
}
}
使用 java 反射可能是一个完美的主意:
private void initStetho() {
if (BuildConfig.DEBUG) {
try {
Class<?> stethoClazz = Class.forName("com.facebook.stetho.Stetho");
Method method = stethoClazz.getMethod("initializeWithDefaults",Context.class);
method.invoke(null, this);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}
然后我们可以调试编译stetho:
debugCompile 'com.facebook.stetho:stetho:1.5.0'
有更多主要方法连接 stetho 或任何其他库仅用于调试构建 - 使用反射:
1) 通过 debugImplementation 连接您的库 - debugImplementation 'com.facebook.stetho:stetho:1.5.1'
2) 仅使用静态成员实现 class - DynamicClassUtils:
public class DynamicClassUtils {
private static final String TAG = "DynamicClassUtils";
public static void safeInvokeStaticMethod(String fullClassName, String methodName, Class<?>[] types, Object... args) {
try {
Class<?> aClass = Class.forName(fullClassName);
Method aMethod = aClass.getMethod(methodName, types);
aMethod.invoke(null, args);
} catch (Throwable e) {
if (BuildConfig.DEBUG) {
Log.e(TAG, "Error when invoking static method, message: " + e.getMessage() + ", class: " + e.getClass());
e.printStackTrace();
}
}
}
public static <T> T safeGetInstance(String fullClassName, Object... args) {
try {
ArrayList<Class<?>> formalParameters = new ArrayList<>();
for (Object arg : args) {
formalParameters.add(arg.getClass());
}
Class<?> aClass = Class.forName(fullClassName);
Constructor<?> ctor = aClass.getConstructor(formalParameters.toArray(new Class<?>[0]));
return (T) ctor.newInstance(args);
} catch (Throwable e) {
if (BuildConfig.DEBUG) {
Log.e(TAG, "Error when creating instance, message: " + e.getMessage());
e.printStackTrace();
}
return null;
}
}
3) 使用 class 初始化 stetho 及其网络拦截器:
if (BuildConfig.DEBUG) {
Class<?>[] argTypes = new Class<?>[1];
argTypes[0] = Context.class;
DynamicClassUtils.safeInvokeStaticMethod("com.facebook.stetho.Stetho", "initializeWithDefaults", argTypes, this);
}
if (BuildConfig.DEBUG) {
Interceptor interceptor = DynamicClassUtils.safeGetInstance("com.facebook.stetho.okhttp3.StethoInterceptor");
if (interceptor != null) client.addNetworkInterceptor(interceptor);
}
我知道我可以使用 debugCompile
只为 debug build
拉入 dependency
。是否有一种好的、简化的方法来完成所需的 code initialization
?没有依赖项,其他变体将无法编译。
你有几个选择。
选项 1: 为所有构建包含 Stetho(使用 compile
而不是 debugCompile
)并且仅在 Application
class 用于调试版本。
这很容易做到。在你的 Application
class 中,像这样检查 BuildConfig.DEBUG
:
if (BuildConfig.DEBUG) {
Stetho.initialize(
Stetho.newInitializerBuilder(this)
.enableDumpapp(Stetho.defaultDumperPluginsProvider(this))
.enableWebKitInspector(Stetho.defaultInspectorModulesProvider(this))
.build()
);
}
选项 2: 仅包括用于调试版本的 Stetho,并为调试和发布版本创建不同的 Application
classes。
感谢 Gradle,应用程序可以针对不同的构建变体使用不同的源集。默认情况下,您有发布和调试构建类型,因此您可以拥有三个不同的源集:
- 调试 只需要在调试版本中使用的代码
- release 只需要发布版本中的代码
- main 所有构建中你想要的代码
您的应用程序代码目前可能全部在 main
源集中。您可以简单地在应用程序中的 main
文件夹旁边创建一个名为 debug
的新文件夹,并为要为调试构建添加的所有内容镜像 main
文件夹的结构。
在这种情况下,您希望 main
源集中的 Application
class 根本不引用 Stetho。
那么您需要 Application
class 在您的 debug
源集中像往常一样初始化 Stetho。
您可以在 Stetho sample. Specifically, here's the main Application class, and here's the debug Application class 中看到此设置的示例。另请注意,他们在每个源集中设置清单,选择要使用的应用程序 class。
查看@Tanis 的回答。
你也可以这样使用:
仅在 调试版本 上添加库。
dependencies {
debugCompile 'com.facebook.stetho:stetho:1.1.1
}
在您的应用程序中,您可以执行以下操作:
public class ExampleApplication extends Application {
@Override public void onCreate() {
super.onCreate();
StethoUtils.install(this);
}
}
然后你可以在debug/release版本中创建不同的StethoUtils
class。
在src/debug/java/
public class StethoUtils{
public static void install(Application application){
Stetho.initialize(
Stetho.newInitializerBuilder(application)
.enableDumpapp(Stetho.defaultDumperPluginsProvider(application))
.enableWebKitInspector(Stetho.defaultInspectorModulesProvider(application))
.build());
}
}
在src/release/java/
public class StethoUtils{
public static void install(Application application){
// do nothing
}
}
使用 java 反射可能是一个完美的主意:
private void initStetho() {
if (BuildConfig.DEBUG) {
try {
Class<?> stethoClazz = Class.forName("com.facebook.stetho.Stetho");
Method method = stethoClazz.getMethod("initializeWithDefaults",Context.class);
method.invoke(null, this);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}
然后我们可以调试编译stetho:
debugCompile 'com.facebook.stetho:stetho:1.5.0'
有更多主要方法连接 stetho 或任何其他库仅用于调试构建 - 使用反射:
1) 通过 debugImplementation 连接您的库 - debugImplementation 'com.facebook.stetho:stetho:1.5.1'
2) 仅使用静态成员实现 class - DynamicClassUtils:
public class DynamicClassUtils {
private static final String TAG = "DynamicClassUtils";
public static void safeInvokeStaticMethod(String fullClassName, String methodName, Class<?>[] types, Object... args) {
try {
Class<?> aClass = Class.forName(fullClassName);
Method aMethod = aClass.getMethod(methodName, types);
aMethod.invoke(null, args);
} catch (Throwable e) {
if (BuildConfig.DEBUG) {
Log.e(TAG, "Error when invoking static method, message: " + e.getMessage() + ", class: " + e.getClass());
e.printStackTrace();
}
}
}
public static <T> T safeGetInstance(String fullClassName, Object... args) {
try {
ArrayList<Class<?>> formalParameters = new ArrayList<>();
for (Object arg : args) {
formalParameters.add(arg.getClass());
}
Class<?> aClass = Class.forName(fullClassName);
Constructor<?> ctor = aClass.getConstructor(formalParameters.toArray(new Class<?>[0]));
return (T) ctor.newInstance(args);
} catch (Throwable e) {
if (BuildConfig.DEBUG) {
Log.e(TAG, "Error when creating instance, message: " + e.getMessage());
e.printStackTrace();
}
return null;
}
}
3) 使用 class 初始化 stetho 及其网络拦截器:
if (BuildConfig.DEBUG) {
Class<?>[] argTypes = new Class<?>[1];
argTypes[0] = Context.class;
DynamicClassUtils.safeInvokeStaticMethod("com.facebook.stetho.Stetho", "initializeWithDefaults", argTypes, this);
}
if (BuildConfig.DEBUG) {
Interceptor interceptor = DynamicClassUtils.safeGetInstance("com.facebook.stetho.okhttp3.StethoInterceptor");
if (interceptor != null) client.addNetworkInterceptor(interceptor);
}