tags:

views:

372

answers:

3

In a number of questions (like this one) I have been looking into how to "change screens" in my app. I have a "header" on top, with 4 buttons. Each button is meant to replace the "content" (ie change screen):

+--------------------+
| menu with buttons  |
+--------------------+
|                    |
|                    |
|  C O N T E N T     |
|                    |
|                    |
+--------------------+

When I click a Menu button, I run the following code:

@Override
public void onClick(View v)
{
    Intent myIntent = new Intent(BaseActivity.this, ActivityMain.class);
    BaseActivity.this.startActivity(myIntent);
}

As you can see, the startActivity is executed. Now, if I do not specify "launchMode" for the Activity that means that launchMode = normal. If launchMode == normal that means that the Activity will be re-created each and every time I navigate using the top header buttons, and that means that all data entered in "form elements" are gone (or at least hidden).

So, I found the launchMode "singleTask" that sounded sort of nice. If I add that launchMode to my Activity, it will not be re-created when I navigate with the buttons, thus keeping state. Great! Well, until I read this:

As noted above, there's never more than one instance of a "singleTask" or "singleInstance" activity, so that instance is expected to handle all new intents.

I found out that the sentence mean that there can be only one Activity that has the launchMode set to "singleTask" - if I have more than one it wont work (no compiler error though).

This means that I can only "keep the state" for one Activity, when switching back and forth (navigating) between my screens!

Once again, is this really how it supposed to work?

A: 

As noted above, there's never more than one instance of a "singleTask" or "singleInstance" activity, so that instance is expected to handle all new intents.

that means one instance of activity where you've set your "singleTask" or "singleInstance". if you have two activities with that setting it's going to mean you have only two instances. basically set it on as many activities as you like as long as you understand what you're doing.

Alex Volovoy
Hi, no I think you are wrong this time =) At first, I interpreted that as you do above - that the Activity itself can only be instanciated once. So I added the the "singleTask" to two Activities, but that did not work at all... But I might have missed something. The text about these issues on android.com is not very clear...
Ted
I have tested this again: I have two Activities (A and B), both with teh flag "singleTask". Activity B has an EditText. I switch to B (using the header buttons), add som text to the EditText, when switch to Activity A and then back to B. When returning to B, the text in EditText is gone/reset. I did a Log.d("MyApp", "Test") in the onCreate of Activity B and surely enough - the onCreate is executed every single time I navigate to that screen... Thus, singleTask works only for 1 Activity, right?
Ted
A: 

You are trying to solve your problem the easy way but what about when the user changes orientations and your activity is restarted? Won't that wipe out the form? Try it. I think you need to look at saving the state of the form in the bundle. With Android, your activities need to assume that they can be restarted at any time. See below SO post:

http://stackoverflow.com/questions/151777/how-do-i-save-an-android-applications-state

fupsduck
I know about the orientation-problem =) Tahts why I linked to previous questions. Now, I think the whole destroy-and-recreate is really dumb, but I have dealt with that in the Activies (I was forced to, yes). But this thing is something different - its not the same situation I think. I think that when I do the startActivity a new instance of the Activity is creaated and added on top of the stack, thus hiding the previous, perhaps populated, Activity. WHen am I supposed to save the "state" when taht happens? Perhaps is there some other method I need to override? The whole situation is silly =(
Ted
onPause() perhaps... So that would mean not only be prepared for the Activity to get killed, but also "save state" in the onPause-event. *sigh*
Ted
+1  A: 

You seem to be forcing activities to exist where they shouldn't.

If you are going to use buttons as faux tabs, then there should be one activity, no startActivity() calls, and use ViewFlipper or a FrameLayout or something to change your content to match the button. After all, this is how tabs work, and just because you are electing not to use TabHost/TabActivity but roll your own tab-esque system, the design approach should be the same.

CommonsWare
Thx for that. When I first started learning Android, I actually asked that question - "should I create Activities for each screen?". See here: http://stackoverflow.com/questions/2013433/whats-the-right-choice-create-new-activities-or-just-create-a-different-layout-aI took the advice of Christopher =) "You should probably use a separate Activity for each screen..." And to be honest, I think that is want google also meant. When reading I see this: "An activity presents a visual user interface for one focused endeavor the user can undertake..." Sounds about right?
Ted
And if I use just one Activity, there is going to be a lot of code to keep the state, since now all different Layoyts/Views have to be dealt with in one Activity...
Ted
One other thing. I cant really use tabs for navigation, since I need the "header" to have other information too (like images and stuff). So I create my own "tab-ish" thing...
Ted
I stand by my recommendation. Your complaints regarding "a lot of code to keep that state" is going to be required anyway given the concerns you have raised in your question at the top of this page.
CommonsWare
yes, I meant "all code in one place, in the same activity; ie a lot of code in one place..." large file and all that. But I cannot use tabs anyways, since I need other stuff in the header =(
Ted
Then. Don't. Use. Tabs. As I wrote, "there should be one activity, no startActivity() calls, and use ViewFlipper or a FrameLayout or something to change your content to match the button".
CommonsWare