I'm having a hard time managing a back button in my app. If I'm not mistaken, the back button default function should return the user to their previous activity. But when I'm changing from one activity to another I call finish() in the listener. Because of the killed previous activity, pressing back button causes the app to exit.
Is there any way to preserve the previous activity and kill it only after the current activity has changed?
BTW, I know how to override the back button. But if I have a lot of activities, is it efficient to write an override for every activity that doesn't have previous acvitity already killed? I'm developing an RPG and I'm pretty sure there will be a lot of activities.
You're setting yourself up for a really bad time. You want to use as few activities as possible. In a game you really don't want to manage all of that data going back and forward between * amount of activities.
You need models to manage the game data, and your view activity can receive this data from a view controller. You don't want to kill you main view activity and you don't want to keep a bunch of activities in memory. Read a few chapters from this book. Good luck!
http://danielrparente.files.wordpress.com/2013/01/rpg_design_patterns_9_26_05.pdf
Related
When a user enters an activity on my app I want to perform some logic during onStart and possibly launch a second activity before letting the user see the first activity (think of this as a pin protected activity)
I have a small issue where the contents of the first activity are shown for a second before the second activity is started. This happens when the user uses the home button to get out and in to the app. Is there a way to prevent the first activity to be visible at all before performing the logic validation?
This is more of a "design" solution to your problem and not clear if it'll work for you. I had something similar in the app I'm working on. What I did instead, was to create an interstitial Activity that resembled the same starting state (i.e. not yet completely loaded) of the Activity (Pin-protected Activity in your case) that is about to be started. Once I'd made my appropriate decision about whether or not I could go on, I just navigated to that initial Activity. In your case, I could see you making the decision on this interstitial Activity, and then navigating to the Pin-protected Activity or to the other one if conditions were not met properly.
The only downside to this approach is that the app does a quick flash with the additional Activity, but I think the increased separation of logic is worth it.
I have an App with 2 activities A -> B. From B the user can update data being displayed by A, so I want A to show fresh data when the user navigates back (actually not so simple, some network involved so data can be updated at any time).
The activities are listening to ddbb changes so the views can be updated when data changes. Problem is data can change while activities are in background, so I am not sure when and how i should listen for changes. I can think of two approaches:
Listen for changes during the whole Activity lifecycle (onCreate - onDestroy) and just update the views when the data changes. This will update views from background activities.
Listen for changes only when the Activity is being active or displayed (between onStart/onStop or onResume/onPause) and force a view update every time the activity comes to the foreground (since changes might have happened while activity wasn't listening).
Mixed approaches; keep the listeners the whole lifecycle but only update views when activity comes to foreground.
Im not sure which is the correct way to handle data observing while in background.
Option 2 sounds more reasonable, but having to update the views when the activity comes to foreground may lead to UI lag right when the user starts interacting with the activity.
Option 1 will cause a lot of updates every time data is updated.
Thoughts on this?
You can choose any of the three options that suits your particular use case. Though I will say that the conventional use is with start/stop. onStart says that the activity is visible to the user in some way (either fully or partially) and onStop says that the activity is definitely not visible. So if you don't care to update the UI while the activity is not showing at all, use these lifecycle states.
You just may need to be prepared to capture data that you may have missed while the activity was stopped before it gets started again (for example, if the user pressed the home button, then came back to the activity via the task switcher. So performing your query again and rebuilding the contents of views from scratch may be necessary.
I hope you can help me understanding the Android Lifecycle and how I can manage navigation between several kinds if activities. Suppose the following scenario:
Activity A "MainMenu" is started: User clicks on a menuentry
Activity B is started and UI is loaded with content from local database
user interacts with Activity B
user presses Backbutton and returns to Activity A
user presses again the same menuentry for returning to activity B
At the moment: The activity is loaded from scratch
Whished: The previous instance of Activity B with all its UI entries and User interactions should resume
I thought of saving all activities in a static manager. If a activity is started, the manager looks if it has already been started previously. If so, resume the previous activity else startActivity(ActivityA). Is that a good way of handling those navigations? How can I directly resume via code an instance of an activity?
Or is there another way to do this in a better way?
Thanks in advance!
greetings,
faiko
Your not going to be able to "cache" an activity once its off the stack. Activities are very quick to start, Im guessing its your database stuff that is slowing you down. That you could do something about.
In theory, if you knew the user was going to click on entries multiple times going from A -> B, you might want to just load the DB stuff into memory in Activity A, and then send it via Parcel into B. Then when you go back to A, its still in memory, and it will be to go back to B instantly.
If you are unsure of whether this is true, try debugging it and stepping through. You will see the activity is launched fairly quickly, but you need to identify which operations are lagging. From your description above it is probably your database calls, but it could be other things like network calls, or other long standing calls
The life cycle of android activities makes it not possible to start a new intent but keep the old state.
You should save the state of the activity by saving the fields and restore it to this state when needed.
You cannot resume an instance of an activity in the scenario that you have posted. Because due to the android lifecycle, when you press the back button on activity B that activity is destroyed, with all its states and information.
One option to get the information to persist is to extend the Application class and save the information into some variables inside the application class. Although alot of what you do even then can be garbage collected if the system needs the memory. I dont believe there is any good way to have that information persist through the activities even using Jameo's solution, if activity A is killed then if you return to Activity A from activity B then that activity is reloaded and the database access has to happen again.
I have an application that navigates to the same activity but each time the activity loads with different parameters. In my application it's a parsed data content retrieved from url. First thing I want to ask: When I push the backbutton of my device I get my earlier activity without being recreated. Is the objects in this activities alive and can I reference them?
Second question is if my first question doesn't make sense, what do you advice me to do?
If you look at the Activity life cycle, you'll notice that as long as your phone has enough memory, your first activity is kept in memory, and with it any member with the data it contains.
But if your phone needs to have some memory, it can kill any activity kept in background (any activity but the one being shown to the user), which means that you'll loose any data that was in your first activity.
To know which happened, keep in mind that the onResume() method will always be called when your activity is brought to foreground (either on creation, or when you navigate back to it), but onCreate() will be called only when your application is created from scratch (meaning you don't have any saved data).
You should use the bundle mechanism to save data when your activity is paused, and load it when you come back to it. Read the paragraph about Saving Activity state in Android doc to see how to use this.
You are not guaranteed that in memory data will be around once you leave an Activity. Read through this part of the dev guide thoroughly to understand the lifecycle of an Activity: http://developer.android.com/guide/topics/fundamentals/activities.html
If you need to persist information, you should override the onPause, onStop, and/or onDestroy methods of your Activity. You can then save your state using SharedPreferences, the SQLite database, or even a flat file.
In the manifest file add the following to the activity:
android:launchMode="singleTop"
In your example what is happening is when you navigate back to the activity using the back button you are bringing up the activity from the stack. When you navigate to the activity inside of the app what is happening is a NEW activity is being created, while the original is still on the stack. The singleTop launch mode will pop the activity out of the stack if it is there when you navigate to it in the app, and only create a new activity if it is not on the stack.
Without singleTop each time you launch the activity in the app it will create a new instance and you will find there are times you have to hit the back button on the same activity more than once due to multiple instances.
Trying to understand best practice for the lifecycle of my android application, and how activities fit into it.
For example, I have a main activity, sort of the "home" of my application. But, on start-up there are several activities that I 'might' need to run, depending on several cases, one being that it is the first time the app's been run.
Is best practice to call these 'start-up'/house-keeping activities FROM my 'home' activity? Or should the application begin with a 'house-keeping' activities, do the work, then finish() and start the 'home' activity?
Thanks for advice about this,
-- J
For the best user experience (and cleaner code), you really shouldn't chain Activities.
A good best practice for the scenario you describe (needing a particular layout of options on first-launch) is to set a SharedPreference the first time that the "Home" Activity is created. In the same Activity.onCreate() call you should make a decision about what your UI will display based on that saved value (e.g., either set the appropriate View's visibility to View.GONE or choose a different layout.xml altogether).
As an added bonus: You can overload a hypothetical "has been opened" SharedPreference with the version number of the app (e.g., LastOpenedVersion) to be able to present the user with a change log the next time they open your "Home" activity after an upgrade.
I would set your LAUNCHER <intent-filter> on whatever the user will most likely want to go to from their home screen. Presumably, that would be your "home" activity.
In onCreate() of that activity, make the determination if there is some other activity that is needed (e.g., "first-run"), and call startActivity() on it. When the user presses BACK from there (or you finish() that new activity), control will return to your "home" activity.
One possibility is to start from a splash screen Activity (rather than a "home" one), which then determines what to launch next.
You should also consider if your start-up/house-keeping needs to be accomplished via an Activity. If it is not something that the user interacts with, then you can move that functionality into a Service that runs a separate thread.