【问题标题】:Android: 2 aar libraries with the same packageAndroid:2个具有相同包的aar库
【发布时间】:2019-12-12 07:05:07
【问题描述】:

编辑:基于此讨论的后续问题已发布在以下链接中。

Android: How to manage common codebase in multiple libraries used by the same application

我有两个 android aar 库项目:使用 ClassA 的 LibA 和使用 ClassB 的 LibB。两个库具有相同的基本包。两个库都使用同一个名为 BaseClass 的类,当前分别位于包名称“common”中的每个库中。 BaseClass 包含一个名为 baseMethod 的方法。

这会使用同名的类和不同的实现创建两个库。

这是类的样子:

A 类:

package mybasepackage.a;

import mybasepackage.common.BaseClass;

public class ClassA {

    BaseClass baseClass;

    public ClassA() {
        this.baseClass= new BaseClass();
    }

    public String myPublicMethod(){
        return this.baseClass.baseMethod();
    }
}

B 类:

package mybasepackage.b;

import mybasepackage.common.BaseClass;

public class ClassB {

    BaseClass baseClass;

    public ClassB() {
        this.baseClass = new BaseClass();
    }

    public String myPublicMethod(){
        return this.baseClass.baseMethod();
    }
}

LibA 中的基类:

package mybasepackage.common;

 public class BaseClass{

   public String baseMethod() {
        return "Called from ClassA";
    }
}

LibB 中的基类:

package mybasepackage.common;

 public class BaseClass{

   public String baseMethod() {
        return "Called from ClassB";
    }
}

当我尝试在同一个应用程序中编译两个库时,它会抛出一个重复的类 error: "Program type already present: mybasepackage.common.BaseClass",这是因为编译器无法知道要编译哪个 BaseClass,因为它位于两个库中。

我的目标是允许两个 aar 库在同一个应用程序中成功编译,同时为 BaseClass 提供不同的实现。更正式地说,LibA 和 LibB 应该在同一个应用程序中编译,例如:

调用new ClassA().baseMethod() 将返回“Called from ClassA”。

调用new ClassB().baseMethod() 将返回“Called from ClassB”。

前提条件:我无法更改其中一个库中的基本包名称,因为它实质上会造成不必要的 BaseClass 重复。

注意:我知道这可能无法通过 aar 方法实现。如果确实如此,我愿意考虑其他部署架构,只要我能够使用不同的实现使用相同的公共类编译这些库,如问题中所述。

【问题讨论】:

  • BaseClass 包含一个名为 baseMethod 的方法。为什么要使用 BaseClass,而里面的唯一方法应该不同?

标签: java android dependencies android-library


【解决方案1】:

只需构建三个工件,因为两个工件总是需要一个依赖集上的exclude。当两个-liba-libb 库依赖于第三个-base-core-common 库时,没有重复的类 - 如果要保留包名,只需使包名依赖在所有这些上,就像一个元包:

mybasepackage
     |
mybasepackage-liba -> mybasepackage-common
     |
mybasepackage-libb -> mybasepackage-common

mybasepackage-common

【讨论】:

    【解决方案2】:

    鉴于您的先决条件,您不能以这种方式做到这一点。您不能在 java 中有 2 个不同的库具有相同的包名称,这是引发错误的主要问题(而不是类的名称)。

    您可以做的,如果可能的话,最好的处理方法是将两个库合并为一个,并在其中添加两个子包,然后导入它们:

    import mybasepackage.common.a_name.BaseClass; // class A
    import mybasepackage.common.b_name.BaseClass; // class B
    

    这将防止重复错误,因为它们只是具有相同的名称但来自不同的包。

    如果这种方式不符合您的期望,另一个想法是通过实现另一个抽象层来更改架构,在该抽象层中您将 BaseClass 定义为抽象方法:

    package mybasepackage.common;
    
     public class abstract BaseClass{
    
       public String myPublicMethod();
     }
    

    然后你只需在ClassAClassB 中实现方法:

    public class ClassA implements BaseClass{
    
        public ClassA() {
            super();
        }
    
        @Override
        public String myPublicMethod(){
            // logic for A
        }
    }
    

    注意,A 类的上述实现只是一个存根,它不应该按原样工作。适应您的需要。

    无论如何,你不能有两个具有相同类名的包。

    【讨论】:

    • 感谢您的回答。我知道这些解决方案。这个问题以简化的方式类似于我在代码的许多不同部分中遇到的问题。我目前正在寻找的是部署架构级别的解决方案。我试图弄清楚如何使用远程私有存储库上传和下载代码(用 bintray 进行实验)。如果我成功了,我将能够以允许 baseMethod() 为每个类返回正确结果的方式使用来自不同版本的 BaseClass。我会很感激收到你在这个方向上的想法。
    • 出现错误。BaseClass有方法baseMethod,而classA和classB有myPublicMethod方法。
    • 正如@CommonsWare 在另一个答案中指出的那样,不可能将类保持在同一个包中。不管来源。重构是您现在可以采取的最佳选择。使用 bintray,您只是冒着增加更多复杂性来执行会影响性能的无用解决方法的风险
    【解决方案3】:

    我的目标是让两个 aar 库在同一个应用程序中成功编译,同时为 BaseClass 提供不同的实现

    这是不可能的,抱歉。

    我知道这可能无法通过 aar 方法实现。

    这与 AAR 无关。在同一个应用程序句号中,您不能有两个具有相同完全限定类名的类。这些重复的类来自哪里并不重要。

    我愿意考虑其他部署架构,只要我能够使用不同的实现使用相同的公共类编译这些库,如问题中所述。

    这是不可能的,抱歉。再说一遍:重复的类来自哪里并不重要。你根本不能有重复的类。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-05-10
      • 1970-01-01
      • 2017-07-03
      • 1970-01-01
      • 1970-01-01
      • 2017-01-12
      相关资源
      最近更新 更多