【问题标题】:How to create library with modules?如何使用模块创建库?
【发布时间】:2017-01-04 15:33:37
【问题描述】:

我想创建几个库(核心和模块),将所有这些库添加到应用程序并从核心库中的模块调用方法。所有模块都应该是可选的。例如,在我看来:

应用build.gradle:

compile('core-library:1.0@aar')
compile('module1-library:1.0@aar')
compile('module2-library:1.0@aar')
compile('module3-library:1.0@aar')

在每个模块中定义同名的类和方法:

public class ModuleClass {
    public int moduleMethod1() {
        // Do something and return result
        return 1;
    }

    public String moduleMethod2() {
        return "Some String";
    }
}

在核心库中:

for(ModuleClass c : getAllModules()) {
    Log.d("tag", "Result: " + c.moduleMethod1() + " / " + c.moduleMethod2();
}

当然,这只是伪代码。如何实现它或类似的东西?

更新: 核心模块build.gradle

apply plugin: 'com.android.library'

android {
    compileSdkVersion 24
    buildToolsVersion "24.0.3"

    defaultConfig {
        minSdkVersion 9
        targetSdkVersion 24
        versionCode 1
        versionName "1.0"

        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"

        buildConfigField "String[]", "KNOWN_MODULES", "{" +
                "\"module1\"," +
                "\"module2\"" +
                "}"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    compile fileTree(include: ['*.jar'], dir: 'libs')
    compileOnly project(':module1')
    compileOnly project(':module2')
    testCompile 'junit:junit:4.12'
    androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
        exclude group: 'com.android.support', module: 'support-annotations'
    })
}

【问题讨论】:

    标签: android gradle android-library


    【解决方案1】:

    您可以尝试在core-library 中添加List<Class>。当您尝试加载列表时,您必须非常小心,但您应该能够做到。

    首先您的moduleN-library 必须是compileOnly,这样它就不会与core-library 捆绑在一起。

    然后在您的core-library 中保留一个可以安全列出所有可能模块类的单例。

    package com.jbirdvegas.test;
    
    import java.util.HashMap;
    import java.util.Map;
    
    public class ModuleClassManager {
        private static final Object LOCK = new Object();
        private static ModuleClassManager instance;
    
        private Map<Class, Methods> moduleClasses = new HashMap<>();
    
        private ModuleClassManager() {
            try {
                moduleClasses.put(MayNotExist1.class, new MayNotExist1());
            } catch (Exception ignored) {
            }
            try {
                moduleClasses.put(MayNotExist2.class, new MayNotExist2());
            } catch (Exception ignored) {
            }
            try {
                moduleClasses.put(MayNotExist3.class, new MayNotExist3());
            } catch (Exception ignored) {
            }
        }
    
        public static ModuleClassManager getInstance() {
            if (instance == null) {
                synchronized (LOCK) {
                    instance = new ModuleClassManager();
                }
            }
            return instance;
        }
    
        public void callMethodOnAll() {
            moduleClasses.forEach((aClass, methods) -> methods.methodOne());
        }
    
        // the below interface in the real world would be located
        // in the `core-library` and the classes that implement the
        // interface, `Methods` in this example, would exist in the
        // module's they represent.
        interface Methods {
            void methodOne();
        }
    
        class MayNotExist1 implements Methods {
            @Override
            public void methodOne() {
            }
        }
    
        class MayNotExist2 implements Methods {
            @Override
            public void methodOne() {
            }
        }
    
        class MayNotExist3 implements Methods {
            @Override
            public void methodOne() {
            }
        }
    }
    

    或者...使用 OSGi。 OSGi 设置起来比较复杂,但是它可以很好地处理这个用例。

    【讨论】:

    • 谢谢。 compileOnly 可以用于模块吗?代码compileOnly project(':mymodule1') 生成错误Could not find method compileOnly() for arguments [project ':mymodule1'] on object of type org.gradle.api.internal.artifacts.dsl.dependencies.DefaultDependencyHandler。还是我每次都需要手动编译所有模块的 aar 文件?
    • 显示完整的 build.gradle 文件 java 插件应该添加 compileOnly 源集
    • 请查看更新后的问题。我为核心模块添加了完整的 build.gradle。
    猜你喜欢
    • 2020-10-20
    • 1970-01-01
    • 2016-12-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多