android - 如何使用 gradle 将 Reflections 库集成到 android studio 中并保存和收集

标签 android gradle reflection android-gradle-plugin

我的问题与 Reflections 有关@ronmamo 在 github 上的库并将其集成到我的 Android 项目中,以动态访问从某个接口(interface)继承的所有类。

我对 gradle 或 maven 不太熟悉,所以这对我来说是一个学习过程,但我遇到了一个障碍,不知道如何调试/找到这个问题的答案。

正如@ronmamo 所建议的 here ,我想在构建时生成一个包含所有扫描元数据的 xml 文件,并让 Reflections 稍后在我的代码中使用它时收集它:

Although scanning can be easily done on bootstrap time of your application - and shouldn't take long, it is sometime a good idea to integrate Reflections into your build lifecyle. With simple Maven/Gradle/SBT/whatever configuration you can save all scanned metadata into xml/json files just after compile time. Later on, when your project is bootstrapping you can let Reflections collect all those resources and re-create that metadata for you, making it available at runtime without re-scanning the classpath - thus reducing the bootstrapping time.



我不确定我是否完全理解这个“引导”在整个过程中究竟发生在哪里(在 android 应用程序生命周期等方面,甚至是构建时间方面?)所以我不确定在哪里调用 Reflections.collect()。目前,当用户到达程序中的某个点时,我稍后会在我的应用程序中调用它。

从几个stackoverflow帖子和git自述文件中,我现在想出了这个:([...]表示删除了不相关的代码)

build.gradle(模块:应用程序):
dependencies {
    [...]
    compile 'org.reflections:reflections:0.9.11'
}

build.gradle(项目:MyProject):
buildscript {
    repositories {
        jcenter()
        mavenCentral()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:2.3.3'
        classpath 'org.reflections:reflections:0.9.11'
    }
}

allprojects {
    repositories {
        jcenter()
    }
}

task runReflections {
    doLast {        
        org.reflections.Reflections("f.q.n").save("${sourceSet.main.output.classesDir}/META-INF/reflections/myproject-reflections.xml")
    }
}

task clean(type: Delete) {
    delete rootProject.buildDir
}

稍后在我的代码中(通过用户输入在某个时候到达此类,而不是在应用程序启动时加载):
Reflections reflections = Reflections.collect(); 
Set<Class<? extends MyInterface>> allClasses = reflections.getSubTypesOf(MyInterface.class);

这会产生以下异常,因为“reflections”没有被实例化并且具有“null”的值:
Attempt to invoke virtual method 'java.util.Set org.reflections.Reflections.getSubTypesOf(java.lang.Class)' on a null object reference

我知道生成的 .xml 文件位于进行构建的计算机上,我不确定这是否也传输到了 android 设备,所以我猜这就是失败的原因。但是在 apk 传输并在我的 android 设备上运行之前,我的 Java 代码在什么时候可以访问该文件?

我已经尝试从不同的角度以多种不同的方式进行谷歌搜索,但我似乎无法找到使反射在 Android 中工作的解决方案。我理解这里解释的原理,在构建时在 xml 文件中生成信息以在运行时提供类信息似乎更好。但是我怎样才能正确设置呢?

谢谢

最佳答案

这里有一点先有鸡还是先有蛋的问题要解决

  • 你想要Reflections访问从 src/main/java 编译的类的 API
  • Gradle 任务和 Reflections类由 Gradle 的 buildscript 加载类加载器
  • src/main/java 中的类在 buildscript 之后编译类加载器定义为

  • 您需要引入另一个可以访问已编译类以打破循环依赖的类加载器。然后可以将其传递给 Reflections .例如:
    buildscript {
        classpath 'org.reflections:reflections:0.9.11'
    }
    task doReflectyStuff {
        dependsOn compileJava
        doLast {
            URL[] urls = sourceSets.main.runtimeClasspath.files.collect {
                it.toURI().toURL()
            }
            ClassLoader classLoader = new URLClassLoader(urls, null)
            Configuration config = new ConfigurationBuilder("com.mypackage", classLoader)
            Reflections reflections = new ReflectionsBuilder(config)
            ...
        }
    }
    

    here对于类似的问题

    关于android - 如何使用 gradle 将 Reflections 库集成到 android studio 中并保存和收集,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45130871/

    相关文章:

    java - 无法加载包装器属性,属性文件包含xml中的代码

    java - 使用反射从 POJO 获取 id 列名称

    c# - 使用 GetType() 创建 List<T>

    java - 无法在 android TextView 中打印 JSON 对象字符串

    java - 类加载器 : Resources from Callee

    android - 通过 bundle 传递新数据来恢复旧 Activity

    intellij-idea - 让 Intellij IDEA (13+) 识别 Gradle 模块相互依赖关系

    java - 如何对带有String、String、String...作为参数的方法进行反射调用?

    Android 在主要 Activity 之前检查权限

    android - appcompat-v7 :27. 1.1 与 firebase-ads :15. 0.1 冲突