如何在Android库项目中覆盖一个类?

15
以下是我的情况:
我有一个库项目和一个基于它的项目。现在在库中,我有两个类A和B,其中A使用B。在使用该库的项目中,我有另一个类B,它应该覆盖库中的B类。
但每次A类调用时,它最终都会进入库中的B类。我该如何告诉Android应该使用项目中的B类,而不是库中的B类?

你的库和B库是否在同一个包中? - mohamede1945
我不确定我理解你的问题。A和B都在库中,因为A将被其他项目共享,并且A需要B。类B对于每个项目的实现方式都不同,因此每个项目应该使用自己的Class B(以及来自库的Class A)。 - VKurt
好的,根据这个新信息,我会回答你的问题。 - mohamede1945
3个回答

4

当前布局无法使用该方法。你需要使用策略模式。在你的库中定义一个名为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的类型或名称。

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

要将Intent的创建移动到你的库中,你可以使用策略、模板或工厂方法模式等策略。参见维基百科上的设计模式,了解更多与你的库设计相匹配的(创造性的)模式。

一个简单的解决方案是:

创建一个抽象的LibraryActivity,并从中扩展你的项目活动。 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 类呢?因为这些类没有构造函数。 - Tony Chan
@Turbo,我增加了一个例子,用于在不能使用自定义构造函数的情况下进行操作。 - thaussma
感谢您提供的额外答案。为了澄清,这意味着如果LibActivity不是根活动(即它实际上是从另一个活动(比如MainActivity)启动的),那么我们需要继续使用覆盖和工厂方法来沿着链条进行修改吗?我之所以问这个问题,是因为有时需要修改的活动可能距离当前活动有几个屏幕/活动。 - Tony Chan
我觉得我不太明白你的问题。在我的例子中,LibActivity是抽象的,不能被实例化。这里的代码展示了如何实现一个库,允许在使用该库时自定义某些任务。 - thaussma
抱歉,我错过了那个关键字。我的问题是,假设你有两个项目,每个项目都需要返回它们自己修改后的LibB类。它们各自都有扩展LibActivity的活动,但是如果核心库项目代码通过意图启动LibActivity,则需要在意图中提供该类的名称。由于我们有两个项目应用程序,所以有两个名称。最终,我使用了这个问题的答案:https://dev59.com/pWkw5IYBdhLWcg3wXZT8 虽然我想知道你的方法是否可行。 - Tony Chan

1

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

我从项目中创建一个类A,这个类继承自库项目

public class A extends libraryProject_A{

//here i put all methods from the new class B to override methods from library class B

}

0

从您的评论中我看到您有一个使用类B的A类

但是根据您使用的项目,类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.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接