我的问题与 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 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/