14

I know that I cannot pass parameters to the Activity constructor in android, but I would like to understand why.

What I tried to do is:

CalorieSelectorActivity csa = new CalorieSelectorActivity(userName);
                Intent i = new Intent(thisContext, csa.getClass());
                startActivity(i);

I have defined the class as follows:

public class CalorieSelectorActivity extends Activity {

public CalorieSelectorActivity(String name) {
    super();

}

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.calorieselector);

}
}

And it works perfectly when I remove the parameters from the constructor. I finally did it using intent.putExtra, but am very curious to know why it cannot be done by passing parameters to the constructor?

LogCat:

02-04 06:46:52.257: W/dalvikvm(800): threadid=1: thread exiting with uncaught exception (group=0x4001d800)
02-04 06:46:52.277: E/AndroidRuntime(800): FATAL EXCEPTION: main
02-04 06:46:52.277: E/AndroidRuntime(800): java.lang.RuntimeException: Unable to instantiate activity ComponentInfo{com.manarbushnaq.calorietracker/com.manarbushnaq.calorietracker.CalorieSelectorActivity}: java.lang.InstantiationException: com.manarbushnaq.calorietracker.CalorieSelectorActivity
02-04 06:46:52.277: E/AndroidRuntime(800):  at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2585)
02-04 06:46:52.277: E/AndroidRuntime(800):  at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2679)
02-04 06:46:52.277: E/AndroidRuntime(800):  at android.app.ActivityThread.access$2300(ActivityThread.java:125)
02-04 06:46:52.277: E/AndroidRuntime(800):  at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2033)
02-04 06:46:52.277: E/AndroidRuntime(800):  at android.os.Handler.dispatchMessage(Handler.java:99)
02-04 06:46:52.277: E/AndroidRuntime(800):  at android.os.Looper.loop(Looper.java:123)
02-04 06:46:52.277: E/AndroidRuntime(800):  at android.app.ActivityThread.main(ActivityThread.java:4627)
02-04 06:46:52.277: E/AndroidRuntime(800):  at java.lang.reflect.Method.invokeNative(Native Method)
02-04 06:46:52.277: E/AndroidRuntime(800):  at java.lang.reflect.Method.invoke(Method.java:521)
02-04 06:46:52.277: E/AndroidRuntime(800):  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)
02-04 06:46:52.277: E/AndroidRuntime(800):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)
02-04 06:46:52.277: E/AndroidRuntime(800):  at dalvik.system.NativeStart.main(Native Method)
02-04 06:46:52.277: E/AndroidRuntime(800): Caused by: java.lang.InstantiationException: com.manarbushnaq.calorietracker.CalorieSelectorActivity
02-04 06:46:52.277: E/AndroidRuntime(800):  at java.lang.Class.newInstanceImpl(Native Method)
02-04 06:46:52.277: E/AndroidRuntime(800):  at java.lang.Class.newInstance(Class.java:1429)
02-04 06:46:52.277: E/AndroidRuntime(800):  at android.app.Instrumentation.newActivity(Instrumentation.java:1021)
02-04 06:46:52.277: E/AndroidRuntime(800):  at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2577)
02-04 06:46:52.277: E/AndroidRuntime(800):  ... 11 more
hasanghaforian
  • 13,858
  • 11
  • 76
  • 167
Manar Bushnaq
  • 192
  • 1
  • 1
  • 8

5 Answers5

27

Refer to your code:

CalorieSelectorActivity csa = new CalorieSelectorActivity(userName);

Intent i = new Intent(thisContext, csa.getClass());

startActivity(i);

Even if you create an object of your activity, what you are "passing" in the Intent object is not the activity object but just the class of your activity. In startActivity() the Android framework will try to instantiate an object of your activity. And it calls the default constructor (without parameters) when it does that. It fails when your class does not have a constructor without parameters.

Of course, you have found the correct solution, pass the parameters as part of Intent object.

hasanghaforian
  • 13,858
  • 11
  • 76
  • 167
Sameer
  • 4,379
  • 1
  • 23
  • 23
  • I was initially trying to do that so that I can pass a custom object into the activity class because I needed to use it there, but when that failed I tried a simple string. As show in my question. Then I surrendered and passed it through the intent.@Sameer – Manar Bushnaq Feb 04 '12 at 06:30
  • And what about the fact that my class declaration has an argument, and the object "csa" that I define is based on that class. Shouldn't Android be trying to call that class constructor (which eventually calls the default Activity constructor) instead of calling the default Activity constructor straight away. I find that very strange behavior. @DallaRosa – Manar Bushnaq Feb 04 '12 at 06:39
  • 2
    I am not really an expert on how Android framework is implemented. However, essential thing to understand here is that the framework uses reflection to instantiate the object of your activity. The object you created is not being used by the framework. I would suggest you read up on Java reflection. Then it may not seem that strange. – Sameer Feb 04 '12 at 11:23
  • @Sameer: you're totally right. As the Android framework expects a constructor with no parameters the apps crashes cause the only available constructor is expecting an argument. – DallaRosa Feb 05 '12 at 22:35
7

I'm surprised that nobody answered the actual question asked! So to answer this Why I cannot pass parameters to Android Activity Constructor: because Android calls the constructor of the Activity and the only constructor Android calls is the default constructor which of course you can override but "It doesn't matter whether you add it or not, and there is no context in which it can be employed in a useful way.".

So as there is no way you can pass your parameters to default constructor, you cannot employ it to work for you.

Marian Paździoch
  • 8,813
  • 10
  • 58
  • 103
1

If you really need to create an Activity that has a constructor (because, say, you're creating an Activity that will be launched by another app, such as the edit activity of a Tasker plugin), you can do it by using a derived class, as so:

class BaseActivity extends Activity
{
    public BaseActivity(String parameter)
    {
        // Do something with parameter
    }
}

class DerivedActivity extends BaseActivity
{
    public DerivedActivity()
    {
        super("parameter");
    }
}

If you need to generate the parameter, replace "parameter" with a function call that returns the appropriate value.

Trebor Rude
  • 1,904
  • 1
  • 21
  • 31
1

Try to use extras to pass values between activities:

Intent intent = new Intent(getBaseContext(), CalorieSelectorActivity.class);
intent.putExtra("username", userName);
startActivity(intent);

Access that intent on next activity in the onCreate method:

String userName = getIntent().getStringExtra("username");

Another option is use static variables but I don't know if this is a good practice.

israteneda
  • 705
  • 1
  • 14
  • 26
-1

What error do you get when you try and call the constructor? You can pass values into new instances of your Activity by calling its construction. It might or might not solve your problem but what happens if you annotate your constructor with @override?

That said, you really should be using Bundles or the intent.put methods to make data available to them since those values can be restored by the system if your Activity is paused to free up memory.

David C. Sainte-Claire
  • 2,461
  • 1
  • 15
  • 12
  • The error I am getting is: 02-04 03:39:58.297: E/AndroidRuntime(713): java.lang.RuntimeException: Unable to instantiate activity ComponentInfo{com.manarbushnaq.calorietracker/com.manarbushnaq.calorietracker.CalorieSelectorActivity}: java.lang.InstantiationException: com.manarbushnaq.calorietracker.CalorieSelectorActivity I did not want to fiddle with the constructure, that's why I am calling the super(). As I said before though it works fine when I use the same code except without parameters. It works with every other class except Activity!!! – Manar Bushnaq Feb 04 '12 at 03:58