在API中使用静态工厂方法

时间:2014-05-11 17:46:38

标签: java android module

我正在编写一个基本上只有一个自定义Activity的小型库:

package com.example.android.somelibrary;

public class CustomActivity extends Activity {

    private static final String EXTRA_SOME_THING = "CustomActivity.EXTRA_SOMETHING";

    public static Intent newIntent(Context context, int arg1) {
        Intent intent = new Intent(context, CustomActivity.class);
        intent.putExtra(EXTRA_SOME_THING arg1);
        return intent;
    }

    //... other methods
}

我希望此库的用户能够扩展此活动:

package com.example.android.myproject;

public class MyCustomActivity extends CustomActivity {
    //... some methods
}

但我希望用户能够依赖我的公共工厂newInstance()

// start MyCustomActivity
int someInt = 0;
Intent intent = MyCustomActivity.newIntent(getApplicationContext(), someInt);
startActivity(intent);

然而,当我尝试以这种方式开始活动时,我收到错误:

android.content.ActivityNotFoundException: Unable to find explicit activity class {com.example.android.myproject/com.example.android.somelibrary.CustomActivity}; have you declared this activity in your AndroidManifest.xml?

我在各自的清单中声明了两个活动:SomeLibrary的清单中的CustomActivity和MyProject清单中的MyCustomActivity。

我感到困惑,因为如果我改变了开始活动,那么一切正常:

Intent intent = new Intent(context, MyCustomActivity.class);
startActivity(intent);

这让我觉得我已经在MyProject中正确设置了所有模块依赖项。这只是Java的限制吗?我不能以这种方式调用静态方法(在子节点上调用父方法)吗?

1 个答案:

答案 0 :(得分:1)

这不起作用。

CustomActivity.newIntent()是CustomActivity类上定义的静态方法。该静态方法返回一个指向CustomActivity.class的Intent。

因此,当您调用MyCustomActivity.newIntent()时,您会得到什么?指向CustomActivity.class的intent。因为这就是CustomActivity中定义的方法。触发该意图将无效,因为您的应用清单中未定义CustomActivity。无论如何,这无关紧要,因为您想启动MyCustomActivity,而不是CustomActivity。

你想要的是一个“知道”它被调用的类名的静态方法。不幸的是,这在Java中是不可能的。

现在,说了......我要告诉你该怎么做。不过我不推荐它。 (我稍后会说为什么会这样做)

无论如何,就像我说的:静态方法不知道它们被调用了什么类。但实例方法确实如此。所以你可以这样做:

public class CustomActivity extends Activity {

    private static final String EXTRA_SOME_THING = "CustomActivity.EXTRA_SOMETHING";

    public Intent newIntent(Context context, int arg1) {
        Intent intent = new Intent(context, getClass());
        intent.putExtra(EXTRA_SOME_THING arg1);
        return intent;
    }

    //... other methods
}

同样的事情,但是:

  • 这是一个实例方法,而不是静态
  • 我们说getClass()(动态返回当前实例的类)而不是说CustomActivity.class(总是指向CustomActivity类)。

然后,如果我们使用MyCustomActivity扩展CustomActivity,我们可以像这样创建一个MyCustomActivity意图:

Intent i = new MyCustomActivity().newIntent(getActivity(), 1);

它会起作用。

为什么我不推荐这个:

  • 这很难看,也很奇怪。如果你想做某事而语言让它变得丑陋和粗暴,hansolov(“让语言获胜”);
  • 它启用的技术不是一个好主意。

让我继续谈谈这一点。遗传很像注塑塑料:我们看到这种技术用来制造我们每天都依赖的工具,但如果我们在家里做,我们可能会弄得一团糟。

那是因为继承比看起来更难。如果三个活动都需要使用一个特定类型的参数,这是否意味着它们都应该是相同的活动类型?可能不是。我没有空间或时间进入它(其他人说它比我更好),但足以说有很多以这种方式共享代码的陷阱。

这是否意味着他们可以用另一种方式共享一些代码?当然!将实现放在另一个类中,并在您自己的静态newIntent()方法中调用。这是一个更多的代码,但它没有这个陷阱。所以我建议改为做。