Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/213.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何使用gradle和save and collect在android studio中集成反射库_Android_Gradle_Reflection_Android Gradle Plugin - Fatal编程技术网

如何使用gradle和save and collect在android studio中集成反射库

如何使用gradle和save and collect在android studio中集成反射库,android,gradle,reflection,android-gradle-plugin,Android,Gradle,Reflection,Android Gradle Plugin,我的问题与github上的@ronmamo库有关,并将其集成到我的Android项目中,以动态访问从某个接口继承的所有类 我对gradle或maven不太熟悉,所以这对我来说是一个学习过程,但我遇到了一个障碍,不知道如何调试/找到这个问题的答案 正如@ronmamo所建议的,我希望在构建时生成一个包含所有扫描元数据的xml文件,并在以后的代码中使用它时让反射收集它: 虽然扫描可以很容易地在您的 应用程序-而且不会花费很长时间,有时这是一个好主意 将反射集成到构建生命周期中。简单的 Maven/G

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

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

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

虽然扫描可以很容易地在您的 应用程序-而且不会花费很长时间,有时这是一个好主意 将反射集成到构建生命周期中。简单的 Maven/Gradle/SBT/任何可以保存所有扫描数据的配置 在编译后将元数据转换为xml/json文件。后来呢, 您的项目正在启动,您可以让反射收集所有 并为您重新创建元数据,使其 在运行时可用,无需重新扫描类路径-从而减少 启动时间

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

从几篇stackoverflow文章和git自述文件中,我现在已经想到了:([…]表示删除了不相关的代码)

build.gradle(模块:应用程序):

build.gradle(项目:MyProject):

稍后在我的代码中(该类在某个点通过用户输入到达,而不是在应用程序启动时加载):

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

我试过从不同的角度用多种不同的方式在谷歌上搜索,但我似乎找不到一个解决方案来让反射在Android上工作。我理解这里解释的原理,似乎最好在构建时在xml文件中生成信息,以便在运行时提供类信息。但是我怎样才能正确地设置它呢


谢谢

这里有一点鸡或蛋的问题需要解决

  • 您希望
    Reflections
    API访问从
    src/main/java
  • Gradle任务和
    反射
    类由Gradle的
    构建脚本
    类加载器加载
  • src/main/java
    中的类是在定义了
    buildscript
    classloader之后编译的
  • 您需要引入另一个可以访问已编译类的类加载器,以打破循环依赖关系。然后可以将其传递到
    反射
    。例如:

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

    类似的问题请参见这里有一点鸡或蛋的问题需要解决

  • 您希望
    Reflections
    API访问从
    src/main/java
  • Gradle任务和
    反射
    类由Gradle的
    构建脚本
    类加载器加载
  • src/main/java
    中的类是在定义了
    buildscript
    classloader之后编译的
  • 您需要引入另一个可以访问已编译类的类加载器,以打破循环依赖关系。然后可以将其传递到
    反射
    。例如:

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

    类似的问题请参见

    几天来,我一直在尝试在Android中使用Reflections,这就是我迄今为止所取得的成果。我在项目的build.gradle中创建了一个任务:

    task myTask(dependsOn: compileJava) {
        doLast {
            URL[] urls = sourceSets.main.runtimeClasspath.files.collect {
                it.toURI().toURL()
            }
            ClassLoader classLoader = new URLClassLoader(urls, ClassLoader.systemClassLoader)
            org.reflections.Configuration config = new ConfigurationBuilder()
                    .addClassLoader(classLoader)
                    .filterInputsBy(new FilterBuilder().include(FilterBuilder.prefix("com.company.project")))
                    .addScanners(new SubTypesScanner(false))
            Reflections reflections = new Reflections(config)
            reflections.save("${sourceSets.main.output.classesDirs}/META-INF/reflections/mcommerce-reflections.json", new JsonSerializer())
        }
    }
    
    dependencies {
        classpath 'org.reflections:reflections:0.9.10'
    }
    
    afterEvaluate {
        android.applicationVariants.each { variant ->
            variant.javaCompiler.doLast {
                // get JAR file that contains the classes
                def collection = project.configurations.compile*.toURI().find { URI uri -> new File(uri).name.startsWith("startOfJarFileNameHere") }
                URL[] urls = collection.collect {
                    println "Collecting classes using Reflections from " + it
                    it.toURL()
                }
    
                // collect all classes
                ClassLoader classLoader = new URLClassLoader(urls, ClassLoader.systemClassLoader)
                org.reflections.Configuration config = org.reflections.util.ConfigurationBuilder
                        .build("package.name.of.interest.here")
                        .addClassLoader(classLoader)
                        .setUrls(urls)
                org.reflections.Reflections reflections = new org.reflections.Reflections(config)
    
                // save as JSON file into the assets folder
                // (a) generate file for current debug or release build
                reflections.save(
                    "${variant.javaCompiler.destinationDir}/../../assets/${variant.buildType.name}/reflections/my-reflections.json",
                        new org.reflections.serializers.JsonSerializer())
                // (b) always update fall-back file for debug (used when running app from Android Studio or IntelliJ)
                reflections.save(
                        "${variant.javaCompiler.destinationDir}/../../../../src/debug/assets/reflections/my-reflections.json",
                        new org.reflections.serializers.JsonSerializer())
            }
        }
    }
    
    稍后,在项目中的一个类上,我实例化了反射,就像在GitHub的示例中所做的那样(我使用Kotlin):

    如果在终端上运行myTask,则构建成功,但我收到消息“给定扫描URL为空。在配置中设置URL”,我在Google中搜索了此消息,但没有找到任何有用的内容

    我尝试了在gradle文件上配置反射的不同方法,但是当我收集它们时,我总是收到一个空实例


    我希望我的答案对某些人有用。

    几天来,我一直在尝试在Android中使用Reflections,这就是我迄今为止所取得的成就。我在项目的build.gradle中创建了一个任务:

    task myTask(dependsOn: compileJava) {
        doLast {
            URL[] urls = sourceSets.main.runtimeClasspath.files.collect {
                it.toURI().toURL()
            }
            ClassLoader classLoader = new URLClassLoader(urls, ClassLoader.systemClassLoader)
            org.reflections.Configuration config = new ConfigurationBuilder()
                    .addClassLoader(classLoader)
                    .filterInputsBy(new FilterBuilder().include(FilterBuilder.prefix("com.company.project")))
                    .addScanners(new SubTypesScanner(false))
            Reflections reflections = new Reflections(config)
            reflections.save("${sourceSets.main.output.classesDirs}/META-INF/reflections/mcommerce-reflections.json", new JsonSerializer())
        }
    }
    
    dependencies {
        classpath 'org.reflections:reflections:0.9.10'
    }
    
    afterEvaluate {
        android.applicationVariants.each { variant ->
            variant.javaCompiler.doLast {
                // get JAR file that contains the classes
                def collection = project.configurations.compile*.toURI().find { URI uri -> new File(uri).name.startsWith("startOfJarFileNameHere") }
                URL[] urls = collection.collect {
                    println "Collecting classes using Reflections from " + it
                    it.toURL()
                }
    
                // collect all classes
                ClassLoader classLoader = new URLClassLoader(urls, ClassLoader.systemClassLoader)
                org.reflections.Configuration config = org.reflections.util.ConfigurationBuilder
                        .build("package.name.of.interest.here")
                        .addClassLoader(classLoader)
                        .setUrls(urls)
                org.reflections.Reflections reflections = new org.reflections.Reflections(config)
    
                // save as JSON file into the assets folder
                // (a) generate file for current debug or release build
                reflections.save(
                    "${variant.javaCompiler.destinationDir}/../../assets/${variant.buildType.name}/reflections/my-reflections.json",
                        new org.reflections.serializers.JsonSerializer())
                // (b) always update fall-back file for debug (used when running app from Android Studio or IntelliJ)
                reflections.save(
                        "${variant.javaCompiler.destinationDir}/../../../../src/debug/assets/reflections/my-reflections.json",
                        new org.reflections.serializers.JsonSerializer())
            }
        }
    }
    
    稍后,在项目中的一个类上,我实例化了反射,就像在GitHub的示例中所做的那样(我使用Kotlin):

    如果在终端上运行myTask,则构建成功,但我收到消息“给定扫描URL为空。在配置中设置URL”,我在Google中搜索了此消息,但没有找到任何有用的内容

    我尝试了在gradle文件上配置反射的不同方法,但是当我收集它们时,我总是收到一个空实例


    我希望我的答案对某些人有用。

    我就是这么做的:任务是在Android上为提供依赖项的类(即JAR文件内)使用反射。此解决方案适合我:

    top build.gradle:

    task myTask(dependsOn: compileJava) {
        doLast {
            URL[] urls = sourceSets.main.runtimeClasspath.files.collect {
                it.toURI().toURL()
            }
            ClassLoader classLoader = new URLClassLoader(urls, ClassLoader.systemClassLoader)
            org.reflections.Configuration config = new ConfigurationBuilder()
                    .addClassLoader(classLoader)
                    .filterInputsBy(new FilterBuilder().include(FilterBuilder.prefix("com.company.project")))
                    .addScanners(new SubTypesScanner(false))
            Reflections reflections = new Reflections(config)
            reflections.save("${sourceSets.main.output.classesDirs}/META-INF/reflections/mcommerce-reflections.json", new JsonSerializer())
        }
    }
    
    dependencies {
        classpath 'org.reflections:reflections:0.9.10'
    }
    
    afterEvaluate {
        android.applicationVariants.each { variant ->
            variant.javaCompiler.doLast {
                // get JAR file that contains the classes
                def collection = project.configurations.compile*.toURI().find { URI uri -> new File(uri).name.startsWith("startOfJarFileNameHere") }
                URL[] urls = collection.collect {
                    println "Collecting classes using Reflections from " + it
                    it.toURL()
                }
    
                // collect all classes
                ClassLoader classLoader = new URLClassLoader(urls, ClassLoader.systemClassLoader)
                org.reflections.Configuration config = org.reflections.util.ConfigurationBuilder
                        .build("package.name.of.interest.here")
                        .addClassLoader(classLoader)
                        .setUrls(urls)
                org.reflections.Reflections reflections = new org.reflections.Reflections(config)
    
                // save as JSON file into the assets folder
                // (a) generate file for current debug or release build
                reflections.save(
                    "${variant.javaCompiler.destinationDir}/../../assets/${variant.buildType.name}/reflections/my-reflections.json",
                        new org.reflections.serializers.JsonSerializer())
                // (b) always update fall-back file for debug (used when running app from Android Studio or IntelliJ)
                reflections.save(
                        "${variant.javaCompiler.destinationDir}/../../../../src/debug/assets/reflections/my-reflections.json",
                        new org.reflections.serializers.JsonSerializer())
            }
        }
    }
    
    project build.gradle:

    task myTask(dependsOn: compileJava) {
        doLast {
            URL[] urls = sourceSets.main.runtimeClasspath.files.collect {
                it.toURI().toURL()
            }
            ClassLoader classLoader = new URLClassLoader(urls, ClassLoader.systemClassLoader)
            org.reflections.Configuration config = new ConfigurationBuilder()
                    .addClassLoader(classLoader)
                    .filterInputsBy(new FilterBuilder().include(FilterBuilder.prefix("com.company.project")))
                    .addScanners(new SubTypesScanner(false))
            Reflections reflections = new Reflections(config)
            reflections.save("${sourceSets.main.output.classesDirs}/META-INF/reflections/mcommerce-reflections.json", new JsonSerializer())
        }
    }
    
    dependencies {
        classpath 'org.reflections:reflections:0.9.10'
    }
    
    afterEvaluate {
        android.applicationVariants.each { variant ->
            variant.javaCompiler.doLast {
                // get JAR file that contains the classes
                def collection = project.configurations.compile*.toURI().find { URI uri -> new File(uri).name.startsWith("startOfJarFileNameHere") }
                URL[] urls = collection.collect {
                    println "Collecting classes using Reflections from " + it
                    it.toURL()
                }
    
                // collect all classes
                ClassLoader classLoader = new URLClassLoader(urls, ClassLoader.systemClassLoader)
                org.reflections.Configuration config = org.reflections.util.ConfigurationBuilder
                        .build("package.name.of.interest.here")
                        .addClassLoader(classLoader)
                        .setUrls(urls)
                org.reflections.Reflections reflections = new org.reflections.Reflections(config)
    
                // save as JSON file into the assets folder
                // (a) generate file for current debug or release build
                reflections.save(
                    "${variant.javaCompiler.destinationDir}/../../assets/${variant.buildType.name}/reflections/my-reflections.json",
                        new org.reflections.serializers.JsonSerializer())
                // (b) always update fall-back file for debug (used when running app from Android Studio or IntelliJ)
                reflections.save(
                        "${variant.javaCompiler.destinationDir}/../../../../src/debug/assets/reflections/my-reflections.json",
                        new org.reflections.serializers.JsonSerializer())
            }
        }
    }
    
    Android上的Java代码:

    InputStream iStream = getAssets().open("reflections/my-reflections.json");
    Configuration config = ConfigurationBuilder.build().setSerializer(new JsonSerializer());
    Reflections reflections = new Reflections(config);
    reflections.collect(iStream);
    Set<Class<? extends MyType>> myTypes = reflections.getSubTypesOf(MyType.class);
    
    InputStream iStream=getAssets().open(“reflections/my reflections.json”);
    Configuration config=ConfigurationBuilder.build().setSerializer(新的JsonSerializer());
    反射=新反射(配置);
    收集(iStream);
    
    Set我就是这么做的:任务是在Android上为提供依赖项的类(即JAR文件内部)使用反射。此解决方案适合我:

    top build.gradle:

    task myTask(dependsOn: compileJava) {
        doLast {
            URL[] urls = sourceSets.main.runtimeClasspath.files.collect {
                it.toURI().toURL()
            }
            ClassLoader classLoader = new URLClassLoader(urls, ClassLoader.systemClassLoader)
            org.reflections.Configuration config = new ConfigurationBuilder()
                    .addClassLoader(classLoader)
                    .filterInputsBy(new FilterBuilder().include(FilterBuilder.prefix("com.company.project")))
                    .addScanners(new SubTypesScanner(false))
            Reflections reflections = new Reflections(config)
            reflections.save("${sourceSets.main.output.classesDirs}/META-INF/reflections/mcommerce-reflections.json", new JsonSerializer())
        }
    }
    
    dependencies {
        classpath 'org.reflections:reflections:0.9.10'
    }
    
    afterEvaluate {
        android.applicationVariants.each { variant ->
            variant.javaCompiler.doLast {
                // get JAR file that contains the classes
                def collection = project.configurations.compile*.toURI().find { URI uri -> new File(uri).name.startsWith("startOfJarFileNameHere") }
                URL[] urls = collection.collect {
                    println "Collecting classes using Reflections from " + it
                    it.toURL()
                }
    
                // collect all classes
                ClassLoader classLoader = new URLClassLoader(urls, ClassLoader.systemClassLoader)
                org.reflections.Configuration config = org.reflections.util.ConfigurationBuilder
                        .build("package.name.of.interest.here")
                        .addClassLoader(classLoader)
                        .setUrls(urls)
                org.reflections.Reflections reflections = new org.reflections.Reflections(config)
    
                // save as JSON file into the assets folder
                // (a) generate file for current debug or release build
                reflections.save(
                    "${variant.javaCompiler.destinationDir}/../../assets/${variant.buildType.name}/reflections/my-reflections.json",
                        new org.reflections.serializers.JsonSerializer())
                // (b) always update fall-back file for debug (used when running app from Android Studio or IntelliJ)
                reflections.save(
                        "${variant.javaCompiler.destinationDir}/../../../../src/debug/assets/reflections/my-reflections.json",
                        new org.reflections.serializers.JsonSerializer())
            }
        }
    }
    
    project build.gradle:

    task myTask(dependsOn: compileJava) {
        doLast {
            URL[] urls = sourceSets.main.runtimeClasspath.files.collect {
                it.toURI().toURL()
            }
            ClassLoader classLoader = new URLClassLoader(urls, ClassLoader.systemClassLoader)
            org.reflections.Configuration config = new ConfigurationBuilder()
                    .addClassLoader(classLoader)
                    .filterInputsBy(new FilterBuilder().include(FilterBuilder.prefix("com.company.project")))
                    .addScanners(new SubTypesScanner(false))
            Reflections reflections = new Reflections(config)
            reflections.save("${sourceSets.main.output.classesDirs}/META-INF/reflections/mcommerce-reflections.json", new JsonSerializer())
        }
    }
    
    dependencies {
        classpath 'org.reflections:reflections:0.9.10'
    }
    
    afterEvaluate {
        android.applicationVariants.each { variant ->
            variant.javaCompiler.doLast {
                // get JAR file that contains the classes
                def collection = project.configurations.compile*.toURI().find { URI uri -> new File(uri).name.startsWith("startOfJarFileNameHere") }
                URL[] urls = collection.collect {
                    println "Collecting classes using Reflections from " + it
                    it.toURL()
                }
    
                // collect all classes
                ClassLoader classLoader = new URLClassLoader(urls, ClassLoader.systemClassLoader)
                org.reflections.Configuration config = org.reflections.util.ConfigurationBuilder
                        .build("package.name.of.interest.here")
                        .addClassLoader(classLoader)
                        .setUrls(urls)
                org.reflections.Reflections reflections = new org.reflections.Reflections(config)
    
                // save as JSON file into the assets folder
                // (a) generate file for current debug or release build
                reflections.save(
                    "${variant.javaCompiler.destinationDir}/../../assets/${variant.buildType.name}/reflections/my-reflections.json",
                        new org.reflections.serializers.JsonSerializer())
                // (b) always update fall-back file for debug (used when running app from Android Studio or IntelliJ)
                reflections.save(
                        "${variant.javaCompiler.destinationDir}/../../../../src/debug/assets/reflections/my-reflections.json",
                        new org.reflections.serializers.JsonSerializer())
            }
        }
    }
    
    Android上的Java代码:

    InputStream iStream = getAssets().open("reflections/my-reflections.json");
    Configuration config = ConfigurationBuilder.build().setSerializer(new JsonSerializer());
    Reflections reflections = new Reflections(config);
    reflections.collect(iStream);
    Set<Class<? extends MyType>> myTypes = reflections.getSubTypesOf(MyType.class);
    
    InputStream iStream=getAsse