与android.app.Activity的组合

时间:2011-08-30 14:31:30

标签: android inheritance android-activity composition

智慧之源“有效的Java第二”说“赞成组合而非继承”(第16项)。 现在谈到Android活动时,很容易从一个扩展,但是你打破了封装,代码可能会在超类被修改时中断。我试着写作。以下是组件Activity的代码:

public class SimpleActivity extends Activity{
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        TextView textview = new TextView(this);
        textview.setText("This is the Artists tab");
        setContentView(textview);
    }   
}

这是作文。对于每个Activity的生命周期方法,我称之为前向方法。

public class ComposedActivity extends Activity {
    private SimpleActivity act;
    public ComposedActivity(){
        act = new SimpleActivity();
    }

    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        act.onCreate(savedInstanceState);
    }   
}

但是应用程序不断崩溃:java.lang.NullPointerException。 我究竟做错了什么 ?只是出于好奇而问。您建议在没有继承的情况下扩展活动吗?

3 个答案:

答案 0 :(得分:6)

您无法在其他活动中真正拥有活动。如果您想使用Android组件的合成,请查看fragments

只需将逻辑分解为非Android组件的普通Java类(POJO),就可以在不使用片段的情况下使用组合。如果他们需要访问活动,您可以在构造函数中传递对目标活动的引用。或者更好的是,让你的活动实现一些界面让他们拥有对它的引用,而不是具体的活动。

答案 1 :(得分:1)

您有一个NullPointerException,因为SimpleActivity.onCreate()会直接调用ComposedActivity,而应该通过使用Intent来调用Activity。因此,当SimpleActivity超级类Intent尝试检索用于激活它的null时,会发现ComposedActivity并崩溃,因为这是意料之外的。

在此Activity展开super.onCreate()之上,但您未从ComposedActivity.onCreate()致电android.app.SuperNotCalledException: Activity did not call through to super.onCreate() 。这通常会引发以下异常:

ComposedActivity

但是阅读你的问题,Activity延伸ComposedActivity可能是错误的。我理解这个问题的方式Activity不应该继承Activity,而是将所有SimpleActivity内容委托给Activity

无论如何,尽管有效Java的智慧源泉,another source of wisdom促进了Activity的继承作为最佳实践。更严重的是,即使我们在教程中找到的代码有时有问题,我认为从Activity继承是迄今为止实现{{1}}的最佳方式:这是由Android设计的。

答案 2 :(得分:1)

我写了一个支持活动和片段组合的图书馆。 https://github.com/passsy/CompositeAndroid

你必须扩展CompositeActivity而不是你能够添加具有相同方法的插件,就像活动本身一样。

实施例

public class MainActivity extends CompositeActivity {

    public MainActivity() {
        addPlugin(new DevOptionsPlugin());
    }
}

插件会在选项菜单中添加一个项目并处理点击次数

public class DevOptionsPlugin extends ActivityPlugin {

    public static final String DEVELOPER_OPTIONS_TEXT = "Developer options";

    @Override
    public boolean onCreateOptionsMenu(final Menu menu) {
        super.onCreateOptionsMenu(menu);
        menu.add(DEVELOPER_OPTIONS_TEXT);

        return true;
    }

    @Override
    public boolean onOptionsItemSelected(final MenuItem item) {
        if (DEVELOPER_OPTIONS_TEXT.equals(item.getTitle())) {
            Intent intent = new Intent(Intent.ACTION_VIEW,
                    Uri.parse("mycompany://appname/devoptions"));
            try {
                // note: simply calling startActivity(intent); is not allowed because the call order 
                // would be different. The code before super.startActivity in this plugin would be executed 
                // first before a plugin added later and is more specialized.
                getActivity().startActivity(intent);
            } catch (ActivityNotFoundException e) {
                Toast.makeText(getActivity(), "Couldn't open Activity", Toast.LENGTH_SHORT).show();
            }
            // not calling super!!!
            return true;
        }

        return super.onOptionsItemSelected(item);
    }
}