Java 通过onCreate方法将自定义参数传递给父活动会产生令人困惑的linter错误

Java 通过onCreate方法将自定义参数传递给父活动会产生令人困惑的linter错误,java,android,inheritance,overriding,oncreate,Java,Android,Inheritance,Overriding,Oncreate,为什么通过onCreate方法将自定义参数传递给父活动,而将根方法的重写留给父活动,会导致以下linter错误: 重写方法应调用super.onCreate 背景 例如,我有一个MainActivity类,它从ParentActivity扩展而来,ParentActivity扩展了Android的活动 为了使我的应用程序更抽象,我尝试在ParentActivity中处理一些开发者在开发和使用MainActivity时不需要看到的事情 我有几个参数要传递给ParentActivity,比如bo

为什么通过onCreate方法将自定义参数传递给父活动,而将根方法的重写留给父活动,会导致以下linter错误:

重写方法应调用super.onCreate

背景 例如,我有一个MainActivity类,它从ParentActivity扩展而来,ParentActivity扩展了Android的活动

为了使我的应用程序更抽象,我尝试在ParentActivity中处理一些开发者在开发和使用MainActivity时不需要看到的事情

我有几个参数要传递给ParentActivity,比如boolean打开和关闭日志功能,但是似乎通过onCreate()方法传递它们是不~~可能的~~推荐的,因为这会引发linter错误。关于使用自定义方法或直接设置父字段向上传递此类参数到自定义父类的最佳实践,我将提出一个单独的问题,但我希望验证我目前对为什么不可能的理解~~通过现有的onCreate方法和其他参数推荐

试过什么 首先,如果我有一些基本的MainActivity和ParentActivity:

代码0.1 然后尝试向onCreate添加更多参数,例如,用于打开/关闭ParentActivity中的某些记录器功能的布尔值:

代码0.2 Android Studio首先警告我,我没有重写父级的方法,这很有意义,因为它有不同的参数计数,但我认为我可以删除
@Override
,并将其称为good,因为我仍然在ParentActivity中调用
super.onCreate(savedInstanceState)
,这将把savedInstanceState传递给Activity,而我仍然将savedInstanceState从MainActivity传递给ParentActivity。在这一点上,我遇到了我的第一个未知问题:回到MainActivity,我得到一个linter错误

重写方法应调用super.onCreate

令人困惑的是,我确实调用了
super.onCreate(savedInstanceState,logOn)
,就在我得到这个错误的正下方。虽然错误消息的信息不太丰富,但我可以通过调用
super.onCreate(savedInstanceState)
来消除错误,方法是直接调用
super.onCreate(savedInstanceState,logOn)
,即:

代码0.3 使用Android Studio查看工具提示内联文档,我看到
super.onCreate(savedInstanceState)
正在从活动(即父类的父类)和
super.onCreate(savedInstanceState,logOn)调用onCreate方法
正在调用ParentClass的onCreate方法。考虑到典型的继承,并匹配参数长度和类型,这是有意义的

对我来说没有意义的是为什么我必须在MainActivity中调用活动的onCreate方法。为什么在ParentActivity中调用onCreate是不够的?i、 e.为什么代码0.2会抛出linter错误:

重写方法应调用super.onCreate


??我注意到,根据@Code 0.2编译并运行在我的示例智能手机上,但linter错误仍然存在

IDE将在编译时检查
@CallSuper
注释{@code>{@link Activity#onCreate}

我认为这没什么好担心的,因为问题仅限于lint警告。你只是做了一件有点太复杂的事情,让门楣无法跟上;事实上,你的程序不是不正确的

您可以抑制警告(
@supersslint
),或者干脆忽略它

…我可以删除
@覆盖
并称之为好的

我不太确定我是否同意你的看法,在那里。。。删除
@Override
注释并没有任何帮助;linter/编译器仍然知道什么是重写,什么不是重写。我认为注释有用的B/C IDE会告诉你,如果你认为你正在重写一个方法,但实际上你不是,也就是说,由于签名不匹配或某事(AS)。 建议的方法

FWIW,我会用不同的方式解决这个问题。(请注意,代码0.3实际上会导致对基类的两次调用
onCreate()
;这可能是非法的。)我只需更改方法名称(以反映配置和创建之间的语义区别),并在基类中存储一些状态信息:

public class MainActivity extends ParentActivity{
    boolean logOn = true;
    @Override
    protected void onCreate(Bundle savedInstanceState){
        configure(logOn);    //Required, per base class specification
        super.onCreate(savedInstanceState);
        //Do stuff
    }
}
public abstract class ParentActivity extends Activity{

    boolean logOn;
    boolean configured = false;

    /** Subclasses are obligated to call this before calling super.onCreate() */
    protected void configure(boolean logOn)
    {
        this.logOn = logOn;
        this.configured = true;
    }

    @Override
    protected void onCreate(Bundle savedInstanceState){
        if(!configured)
            throw new IllegalStateException("configure() not called prior to onCreate()");

        super.onCreate(savedInstanceState);
        //Do stuff
    }

    @Override
    protected void onDestroy() {
        configured = false;    //(just being pedantic)
    }
}
这真的只是品味的问题

有时人们没有意识到Android可以自动创建活动,比如当它恢复应用程序的后台状态时。(这就是为什么您希望能够将您的
活动
状态序列化和反序列化到捆绑包或从捆绑包中序列化;b/c您的
活动
可能无法使用第一次创建它的相同工作流重新创建)

不过,我认为这不会成为您的问题,因为
ParentActivity
(我声明为
abstract
)总是通过一个具体的子类进行实例化,并且所有子类都保证在其
onCreate()
方法中调用
configure()
。(依我看,
ParentActivity
不会有清单条目,因此系统永远不会尝试自己实例化基类
ParentActivity
。)


只是一些需要注意的事情。(您已在
MainActivity
中将
logOn
设置为常量值,因此如果您计划根据应用程序状态动态更改该值,请在调用
configure()/super.onCreate()之前
,请记住——如果您不采取措施防止它——当您的应用程序恢复到前台时,信息可能会丢失。)

请澄清这是如何解决我的问题的?@greeble31,是的,您
public class MainActivity extends ParentActivity{
    boolean logOn = true;
    @Override
    protected void onCreate(Bundle savedInstanceState){
        super.onCreate(savedInstanceState, logOn);
        //Do stuff
    }
}
public class ParentActivity extends Activity{
    // No longer overriding Activity.onCreate() due to diff in params
    protected void onCreate(Bundle savedInstanceState, boolean logOn){
        super.onCreate(savedInstanceState);
        //Do stuff
    }
}
public class MainActivity extends ParentActivity{
    boolean logOn = true;
    @Override
    protected void onCreate(Bundle savedInstanceState){
        super.onCreate(savedInstanceState);
        super.onCreate(savedInstanceState, logOn);
        //Do stuff
    }
}
public class ParentActivity extends Activity{
    // No longer overriding Activity.onCreate() due to diff in params
    protected void onCreate(Bundle savedInstanceState, boolean logOn){
        super.onCreate(savedInstanceState);
        //Do stuff
    }
}
public class MainActivity extends ParentActivity{
    boolean logOn = true;
    @Override
    protected void onCreate(Bundle savedInstanceState){
        configure(logOn);    //Required, per base class specification
        super.onCreate(savedInstanceState);
        //Do stuff
    }
}
public abstract class ParentActivity extends Activity{

    boolean logOn;
    boolean configured = false;

    /** Subclasses are obligated to call this before calling super.onCreate() */
    protected void configure(boolean logOn)
    {
        this.logOn = logOn;
        this.configured = true;
    }

    @Override
    protected void onCreate(Bundle savedInstanceState){
        if(!configured)
            throw new IllegalStateException("configure() not called prior to onCreate()");

        super.onCreate(savedInstanceState);
        //Do stuff
    }

    @Override
    protected void onDestroy() {
        configured = false;    //(just being pedantic)
    }
}