【问题标题】:How to override a class within an Android library project?如何覆盖 Android 库项目中的类?
【发布时间】:2011-09-27 16:38:06
【问题描述】:

以下是我的情况:

我有一个库项目和一个基于它的项目。现在在库中我有两个类 A 和 B,其中 A 使用 B。在使用库的项目中,我有另一个 B 类,它应该覆盖库中的 B 类。

但是每次 A 类调用时,它都会从库中进入 B 类。 我如何告诉 Android 我的项目中的 B 类应该使用库中的 B 类代替?

【问题讨论】:

  • 库中的 B 和你的都在同一个包中吗?
  • 我不确定我是否理解您的问题。 A 和 B 都在库中,因为 A 将由其他项目共享,而 A 需要 B。每个项目的 B 类实现不同,因此每个项目都应该使用它自己的 B 类(以及库中的 A 类)。
  • 好的,我会根据这个新信息回答你的问题。

标签: android class project android-library


【解决方案1】:

这不适用于当前布局。您必须使用策略模式。在您的库中,使用构造函数定义 LibA,该构造函数在构造函数中采用 LibB 类型的对象:

class LibA{
    LibB b;
    public LibA(LibB b)
        this.b = b;
    }
}

然后你可以在你的项目中重写 LibB 并使用扩展 LibB 的类创建 LibA:

class ProjectB extends LibB{

}

LibA a = new LibA(new ProjectB());

Turbos 问题的答案:

您想从您的库中启动项目活动。所以然后将创建Intent 的代码移到您的项目中,因为只有在您的项目中您才知道要启动的Activity 的类型或名称。

您在评论中提到的解决方案 (here) 通过猜测应该启动的 Activity 的名称在库项目中创建 Intent。这并没有什么问题,但这不是一个优雅的解决方案。您只能启动遵循该特殊命名方案的Activities。因此,您无法启动项目中可见的任意Activities,例如来自其他库的Activities,您无法更改类的名称。

要将 Intent 创建移动到您的库中,您可以使用策略、模板或工厂方法模式。请参阅Design Patterns on Wikipedia 了解更多与您的库设计相匹配的(创造性)模式。

一个简单的解决方案是:

创建一个抽象 LibraryActivity 并从中扩展您的 ProjectActivities。 LibraryActivity 定义了一个返回 Intent 的抽象方法。该抽象方法的实现在您的ProjectActivities 中完成。

abstract class LibActivity{

    private void doSomething(){
        //Library does something

        //and finally calls createIntent() to start an project specific Activity
        startActivity(this.createIntent());
    }

    protected abstract Intent createIntent();
}


class ProjectActivity extends LibActivity{

    protected Intent createIntent(){
        return new Intent(ProjectActivity.this, AnyActivityYouWant.class);
    }        
}

【讨论】:

  • 如何适应 Android Activity 类,因为这些类没有构造函数?
  • @Turbo 我为不能使用自定义构造函数的情况添加了一个示例。
  • 感谢您的额外回答。为了澄清起见,这意味着如果 LibActivity 不是根活动(即它实际上是从另一个活动启动的,比如 MainActivity),那么我们将不得不使用覆盖和工厂方法继续上链?我问是因为有时需要修改的活动距离几个屏幕/活动。
  • 我想我不太明白你的问题。 LibActivity(在我的例子中)不能被实例化——它是抽象的。此处的代码显示了如何实现一个库,允许在使用该库时自定义某些任务。
  • 抱歉,我错过了那个关键字。我的问题是,假设您有 2 个项目,每个项目都需要返回自己的 LibB 修改类。它们每个都有扩展LibActivity 的活动,但是如果有核心库项目代码通过意图启动LibActivity,则需要在意图中提供该类的名称。由于我们有 2 个项目申请,因此有两个名称。我最终使用了这个问题的答案:stackoverflow.com/questions/9951610/… 虽然我想知道你的答案是否可行。
【解决方案2】:

正如我从您的评论中看到的,您的 A 类使用 B 类

但是 B 类应该根据你使用的项目而有所不同。

我认为您需要创建一个基类,例如 BaseB,它将作为 A 类中的一个实例变量,并且您可能为此有一个 setter 和 getter 或者您可以将其作为传递给 A 类的构造函数的参数。并且实例化 A 时,您应该选择使用哪一个。

让我们看看代码

Class A {
 private BaseB b;
 public A(BaseB aB) {
   b = aB;
 }

 public void set(BaseB aB) {
  b = aB;
 }
 public BaseB get() {
   return b;
 }
}

interface BaseB {
}


// in the library have this
class B implements BaseB {
}

// in your project have the other implementation
class B implements BaseB {
}

// you can then instantiate A like this
A a = new A(new B());
// you can choose which one to use here in the previous statement.

【讨论】:

    【解决方案3】:

    我不知道这是否是最好的方法,但我是这样做的;

    我从项目中创建了一个 A 类,这个类从库项目中扩展

    public class A extends libraryProject_A{
    
    //here i put all methods from the new class B to override methods from library class B
    
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-09-18
      • 1970-01-01
      • 2018-01-23
      • 2021-04-04
      • 2012-04-14
      • 1970-01-01
      • 2012-05-28
      • 1970-01-01
      相关资源
      最近更新 更多