智慧之源“有效的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。 我究竟做错了什么 ?只是出于好奇而问。您建议在没有继承的情况下扩展活动吗?
答案 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);
}
}