【问题标题】:Include Stetho only in the debug build variant仅在调试版本变体中包含 Stetho
【发布时间】:2015-05-11 15:57:55
【问题描述】:

我知道我可以使用debugCompile 来只为debug build 拉入dependency。是否有一种好的、简化的方式来执行code initialization 也是必需的?如果没有依赖项,其他变体将无法编译。

【问题讨论】:

  • 这有点复杂,因为您需要 a/ 在您的应用启动时启动 stetho 并 b/ 配置您的 http 客户端以传输到 stetho。您可以通过在调试和发布源文件夹中包含特定版本的类来做到这一点,我觉得不太理想,但它可以工作
  • 即兴发挥,在debug 源集中,创建一个自定义Application 类,它要么扩展Application(如果你没有在其他地方扩展它)或扩展你的自定义Application(如果您在主代码中使用一个。在debug 清单中的<application>android:name 中注册Application。如果您通常使用自定义Application,您可能需要一个tools:replaceNode 属性以及告诉debug 源集替换main 源集清单中的内容。不过还没有尝试过。

标签: android android-studio stetho


【解决方案1】:

检查@Tanis 的答案。

你也可以使用这样的东西:

仅在调试版本上添加库。

dependencies {
   debugCompile 'com.facebook.stetho:stetho:1.1.1      
 }

在您的应用程序中,您可以这样做:

public class ExampleApplication extends Application {

  @Override public void onCreate() {
    super.onCreate();
    StethoUtils.install(this);
  }
}

然后您可以在调试/发布版本中创建不同的StethoUtils 类。

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
   }
}

【讨论】:

  • 注意:如果您声明任何自定义构建类型,您还需要为其创建一个 StethoUtils 类。例如。 src//java/
  • 这意味着您还必须包含 OkHttp 拦截器代码的调试/发布版本。
【解决方案2】:

你有几个选择。

选项 1: 为所有构建包含 Stetho(使用 compile 而不是 debugCompile)并仅在您的 Application 类中初始化它以进行调试构建。

这很容易做到。在您的 Application 类中,检查 BuildConfig.DEBUG,如下所示:

if (BuildConfig.DEBUG) {
    Stetho.initialize(
            Stetho.newInitializerBuilder(this)
                    .enableDumpapp(Stetho.defaultDumperPluginsProvider(this))
                    .enableWebKitInspector(Stetho.defaultInspectorModulesProvider(this))
                    .build()
    );
}

选项 2: 仅包含 Stetho 用于调试版本,并为调试和发布版本创建不同的 Application 类。

感谢 Gradle,应用程序可以为不同的构建变体提供不同的源集。默认情况下,您具有发布和调试构建类型,因此您可以拥有三种不同的源集:

  • debug 只在调试版本中需要的代码
  • release 只在发布版本中需要的代码
  • main 用于所有构建中所需的代码

您的应用程序代码目前可能都在main 源集中。您只需在应用程序中的 main 文件夹旁边创建一个名为 debug 的新文件夹,并为您要为调试构建添加的所有内容镜像您的 main 文件夹的结构。

在这种情况下,您需要在您的 main 源集中有一个完全不引用 Stetho 的 Application 类。

然后,您需要在您的 debug 源集中有一个 Application 类,它可以像往常一样初始化 Stetho。

您可以在Stetho sample 中查看此设置的示例。具体来说,here's the main Application classhere's the debug Application class。另请注意,他们在选择要使用的应用程序类的每个源集中设置清单。

【讨论】:

  • AFAIK,第一种方法不适用于debugCompile,因为该代码将在main 中,并且在main 中不存在依赖关系。
  • 你是对的——这就是为什么我说“在所有版本中都包含 Stetho——”我应该更清楚的是,这意味着使用 compile 而不是 debugCompile。谢谢!
  • 我个人更喜欢第二种方法,因为您的 stetho 代码可能不会在刚刚启用它时结束。您可能想使用转储应用程序、网络绑定,并且不想在生产环境中发布未经测试/调试的代码。
  • 选项 1 不可取,因为您包含库文件但只是不使用它们。
  • in a import ...steho... wrtie especific annotation?
【解决方案3】:

使用 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'

【讨论】:

  • 可能不想捕获所有这些异常或使用字符串加载类(包名称可能会更改)。更清洁的解决方案是使用 gradle 并在需要时注入调试变体。
  • 我相信反射方法是最简单的一种,并且可以保证在发布版本中没有 Stetho 代码而不需要编写代码
  • 只要确保你对类进行 Proguard 以便它即使在缩小后也存在。
  • 为什么要在调试中使用 proguard,如果在极少数情况下我认为您不需要听诊器
【解决方案4】:

有更多的主要方法可以连接 stetho 或任何其他库,仅用于调试构建 - 使用反射: 1) 通过 debugImplementation 连接您的库 - debugImplementation 'com.facebook.stetho:stetho:1.5.1' 2)实现类只有静态成员 - 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) 使用该类来初始化 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);
    }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-10-18
    • 2018-01-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-15
    • 2020-11-21
    • 1970-01-01
    相关资源
    最近更新 更多