Why does passing custom parameters to a parent activity through an onCreate method, while leaving overriding the root method to the parent, result in the following linter error:
Overriding method should call super.onCreate
Background
For example, I have a MainActivity class that extends from ParentActivity that extends Android's Activity.
UML Generator
In order to make my app more abstract I am trying to handle several things in ParentActivity that the developer need not see in their development and use of MainActivity.
I have several parameters I would like to pass to the ParentActivity, like booleans turning on and off log functionalities, but it seems passing them through the onCreate() method is not ~~possible~~ recommended since this throws linter errors. I will make a separate question regarding the best practices for passing such parameters upward to custom parent classes using custom methods or directly setting parent fields, but I was looking to verify my current understanding of why this is not ~~possible~~ recommended through the existing onCreate method and additional parameters.
What has been tried
As a starting point, if I have some basic MainActivity and ParentActivity:
Code 0.1
public class MainActivity extends ParentActivity{
#Override
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
//Do stuff
}
}
public class ParentActivity extends Activity{
#Override
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
//Do stuff
}
}
and then try to add further parameters to onCreate, e.g. a boolean to turn on/off some logger functionality within ParentActivity:
Code 0.2
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
}
}
Android Studio first warns me that I am not overriding the parent's method, which makes sense as it has a different parameter count, but then I thought I can just remove the #Override and call it good since I'm still calling super.onCreate(savedInstanceState) in ParentActivity, which will pass the savedInstanceState up to Activity, and I'm still passing the savedInstanceState to ParentActivity from MainActivity. At this point I encountered my first unknown issue: back in MainActivity, I get a linter error that states
Overriding method should call super.onCreate
Whats confusing is that I do call super.onCreate(savedInstanceState, logOn) directly below where I get this error. Although the error message is not too informative, I can get rid of the error by calling super.onCreate(savedInstanceState) directly above the already existing call to super.onCreate(savedInstanceState, logOn), i.e.:
Code 0.3
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
}
}
Looking at the tooltip inline doc using Android Studio, I see that super.onCreate(savedInstanceState); is calling the onCreate method from Activity (i.e the parent class of ParentClass) and super.onCreate(savedInstanceState, logOn); is calling the onCreate method of ParentClass. With typical inheritance in mind, and matching parameter lengths and types, this makes sense.
What doesn't make sense to me is why I have to call the onCreate method of Activity in MainActivity. Why does the call to onCreate within ParentActivity not suffice? i.e. why does Code 0.2 throw the linter error:
Overriding method should call super.onCreate
? I note, as per the comment by #greeble31 that Code 0.2 compiles, and runs on my example smartphone, but the linter error remains.
I don't think it's too much to worry about, since the problem is limited to a lint warning. You just did something a little too complicated for the linter to follow; your program is not, in fact, incorrect.
You could suppress the warning (#SupressLint), or simply ignore it.
...I can just remove the #Override and call it good...
Not too sure I agree with you, there... Removing the #Override annotation can't really help anything; the linter/compiler still knows what's an override and what's not. I consider the annotation useful b/c the IDE will tell you if you think you're overriding a method, but you're actually not, i.e. due to a signature mismatch or something (as here).
SUGGESTED APPROACH
FWIW, I would've solved this problem a little differently. (Note that code 0.3 actually results in two calls to the base class onCreate(); that's probably illegal.) I would just change the method name (to reflect a semantic distinction between configuration and creation), and store some state information in the base class:
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)
}
}
It's really just a matter of taste.
Sometimes people don't realize that Android can spontaneously create Activities on its own, like when it restores the back-stack state of your app. (This is why you want to be able to serialize and deserialize your Activity state to/from the bundle; b/c your Activity might not be re-created using the same workflow that caused its creation the first time).
I don't think that's going to be an issue for you, though, since ParentActivity (which I've declared as abstract) is always going to be instantiated via a concrete subclass, and all subclasses are guaranteed to call configure() in their onCreate() methods. (IOW, ParentActivity wouldn't have a manifest entry, so the system is never going to try to instantiate a base-class ParentActivity by itself.)
Just something to be aware of. (You had logOn set to a constant value in MainActivity, so if you were planning on changing that dynamically based on the app state, before calling configure()/super.onCreate(), just bear in mind that -- if you don't take steps to prevent it -- that information could be lost when your app is restored to the foreground.)
IDE will check #CallSuper annotation when on compilation {#link Activity#onCreate}.
i wanted to make an app to block incoming call with the help of this blog http://androidsourcecode.blogspot.in/2010/10/blocking-incoming-call-android.html In this blog it only declares only the specific classes but there is no launcher activity like MainActivity.java . I imagine the launcher activity is look like this
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
PhoneCallReceiver abc=new PhoneCallReceiver();
abc.onReceive(getApplicationContext(),getIntent());
setContentView(R.layout.activity_main);
}
}
But it seems this way it does not work. I figure out there is several answer on this topics in stackoverflow. But i don't find which will be my launcher activity and how my app running background continuously .Please give me some link of complete tutorial on this or give me some direction.Thanks in advance:)
I am having trouble trying to use 'requestFeature' in my FRAGMENT. My code is below, I am trying to set the actionbar as an overlay.
#Override
public void onCreate(Bundle savedInstanceState) {
getActivity().requestWindowFeature(Window.FEATURE_ACTION_BAR_OVERLAY);
super.onCreate(savedInstanceState);
I do not want to use a theme because I don't want the whole app to be effected, only this fragment in particular.
You have to call requestWindowFeature() before the setContentView() in the Activity's onCreate() method. This Activity is the one that your fragment is a part of.
I am facing a strange problem suddenly in android. I am creating layout .xml file in res>layout but from a class that extends activity, I can not access it. I have done this several a time but I can not figure out this strange problem. I restarted the eclipse, even the computer but no. When I go for setting the contentView it says something as below :
The method onCreate(Bundle) of type MainActivity must override or implement a supertype method
That is let I have created an xml file at res>layout named "whynot.xml" and from a activity when I try to set it like
setContentView(R.layout.whynot);
It shows red mark below and the above message.
you have to extends Activity and call super.onCreate(savedInstanceState) in the onCreate. For each callback of the Activity's lifecycle is mandatory to call its super
As the error says,
must override or implement a supertype method
you need the super call like
#Override
protected void onCreate(Bundle bundle)
{
super.onCreate(bundle); // here
setContentView(...);
...
}
I am calling from activityA a method that is on activityB.
Method is called from A to B properly but when I execute inside it webviewB.loadUrl(myUrl), app crashes for a nullpointerexception. Same webviewB method, if executed from activityB, works properly. Probably is done because context, when calling from A to B must be set, but how? Which is the best way to do it? Thank you.
ActivityA (tabHost) and ActivityB (tabcontent) are initialized properly and webview from ActivityB shows URL1.
Then when evet from ActivityA is recived, I need to load URL2 on webview from ActivityB.
EDIT:
when event is received on ActivityA,
ActivityB test = new ActivityB();
test.recalcula();
ActivityB,
#Override
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.vistaaib);
webviewB = (WebView) findViewById(R.id.webviewB);
webviewB.loadUrl(URL1);
...
public void recalcula (){
webviewB.loadUrl(URL2);
}
Either intents as suggested by Ortisi. Or Why don't you try creating a class, create that method in this class, And call that method from both the activity.
The best way to communicate between activities is using the Intent mechanism.
So just launch an intent from activityA in order to communicate to activityB that its loadUrl method should run.
Or for other solutions you can read this question:
Best way to accomplish inter-activity communication in an Android TabHost application