2

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?

Community
  • 1
  • 1
Ted
  • 19,727
  • 35
  • 96
  • 154
  • It sounds like you want to use `singleInstance` more than `singleTask` -- there will be only one task anyway, then with only one instance of each of your activities. – Christopher Orr Jan 09 '10 at 12:29
  • Im not following... a "singleInstance" is "always at the root", but I have 4 different screens an they cant all be at the root? Also singleInstance "permits no other activities to be part of its task"... How am I suppose to buil an app with that? The more I learn about Android, the less I understand it seems... =( – Ted Jan 09 '10 at 13:47
  • Christpher: hmm, I tried the "singleInstance" instead, as you suggested, and that works a lot better. Now I dont loose my state in the second Activity. I dont understand why... but it looks alright. hmm... Does that mean that for each Activity with the *singleTask* flag, I get a new Task? from android.com: " A "singleInstance" activity stands alone as the only activity in its task. If it starts another activity, that activity will be launched into a different task..." – Ted Jan 09 '10 at 14:19
  • Yes. The documentation says a task can be thought of as a traditional application with a history stack for your activities. So you want to have a single instance (`singleInstance`) of each Activity within your task, not a single task (application) for each Activity. – Christopher Orr Jan 09 '10 at 16:17

3 Answers3

2

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
  • 986,068
  • 189
  • 2,389
  • 2,491
  • 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-a I 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 Jan 09 '10 at 13:43
  • 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 Jan 09 '10 at 13:44
  • 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 Jan 09 '10 at 13:54
  • 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 Jan 09 '10 at 14:54
  • 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 Jan 09 '10 at 16:02
  • 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 Jan 09 '10 at 16:03
0

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
  • 67,778
  • 13
  • 73
  • 54
  • 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 Jan 09 '10 at 13:40
  • 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 Jan 09 '10 at 14:10
0

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:

Saving Android Activity state using Save Instance State

Community
  • 1
  • 1
fupsduck
  • 3,129
  • 1
  • 19
  • 18
  • 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 Jan 09 '10 at 13:38
  • 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 Jan 09 '10 at 13:57