Thanks for reading by question, albeit a really noob-ish one...
How does the Android system manage memory with regards to activity initialization, specifically if an activity is initialized through other activities? This has been a lingering question in my mind for a while, but I'll try to illustrate with an example:
Say I have 3 activities - A, B and C - with activity A being the one that is launched when the application is started for the very first time. Now, let's say activity A has buttons to navigate to activities B and C, and those activities are launched using Android's startActivity() function, passing it an Intent instance. Similarly, let's say activities B and C have buttons to launch their counterpart activities...make sense so far?
Now, if I then use the startActivity() to:
start activity B from activity A
then start activity C from activity B
then start activity A from activity C
then repeat the above steps indefinitely (so going around in circles)
...would it be fair to assume that the Android system would "know" that the activities had already been started previously and wouldn't re-initialize them and kill more and more memory, but rather call something like the onRestart() functionality to rather "switch" back to an already initialized instance of the activity?
Quite an explanation for a really simple question / problem...apologies if this has already been asked and answered somewhere else...I couldn't find a clear answer anywhere else, even while reading through the Android training section on the Android developers site.
The answer is: It depends. :-)
If you use the standard settings for the activities A, B and C, your application will run out of memory. The reason is that Android will keep each activity in the "Back Stack" that allows the user to navigate back by pushing the back button.
However, if you set the android:launchMode of your activities to singleTop in the AndroidManifest.xml file then Android will route the intents to the running instances of the activities by invoking onNewIntent() in the activity.
You can read more about it in the Android Developer Documentation regarding launch modes.
Related
In my app, I have two activities. Let's call them A and B:
A can launch another A activity or launch B
B can launch A activities only
With this workflow, it's possible to open a long stream of A and B activities. It's even possible to open the same set of data recursively (and therefore keep going until the app crashes).
Sometime in the future, I'll probably implement "singleTask" launchMode with my own activity history.
But for now, what I'd like to do is keep the back stack, but release memory for activities that are not in the foreground (ideally maintaining one active instance per Activity).
I thought that clearTaskOnLaunch would do this for me, but my memory footprint gradually increases as I open one activity after the other. Is this expected behaviour, or does this indicate that I have a memory leak?
Tasks and Back Stack or link this may help you
I have two applications A and B.
Since A and B exchange data by IPC Messenger, I wonder it's ok if I use a Handler handleMessage() event to:
(1) app A is foreground: resume app B (stop stack activity).
(2) app B is foreground: resume app A (stop stack activity).
Now I'm using new intent with ComponentName(packageName, className) to switch between two apps. A and B both have multiple activities, so to resume the top stack activity on the other map, I'm using a message who tell "i'm A, i'm at class A3," so the foreground app B can have the right className to create the launch intent.
Someone have any ideas for me? Thanks,
You can't launch an Application, you can only launch activites. So, if you have different Activities on either side, I think your approach is reasonable.
Alternatively you could create a new Activity per application, which is transparent. This activity should then receive all intents and can delegate them to the activity which should really be opened with FLAG_REORDER_TO_FRONT.
I honestly don't know which approach is better. I think that's more of a design question: use what you like better.
In general: If you have two apps, both developped by you, which are as deeply linked as you describe, think of merging them into one.
I am calling an Intent with String Extra from Activity A -> Activity B .
That works great.
What I'm asking is
When navigate from Activity B -> Activity C and click back, in most cases the activity will be resumed but what if the activity got destroyed by the system? It will be recreated I know but will getIntent() be empty in that case?
Answering your question:
No, it will not be empty.
If you recall a little about the basics of Android you will remember that you can rely on the Extras to send information from an Activity to another through the Intent. If that intent could become empty after a low memory/whatever then you would have lost those Extras as well and you wont be able to successfully recreate the Activity.
Check also this answer for more info:
in Android if OS kills my application, will getIntent() return the Intent with the same extras?
Note that i cant make sure this answer is correct because this is only based on my experience. Feel free to comment.
When navigate from Activity B -> Activity C and click back, in most
cases the activity will be resumed but what if the activity got
destroyed by the system? Will getIntent() be empty in that case?
I have been in a case where the activities must run sequentially, means whatever happens user must be go to activity B (from C - in your case) when onBackPressed fired.
I put some log in onPause and onDestory to see if my apps removed by the OS because it needs some free memory. Then, i test it with my old phone with low RAM (first generation HTC desire) and open a lot apps to make sure the RAM usage will be full.
The result?
Yes, my old phone destroyed my apps (from logcat). Fortunately, after my current activity restarted, the onBackPressed is still working fine (going back to previous activity).
I have an Android app with 2 primary activities. When the app starts from scratch, both activities start and run just fine. Something like: A -> B. Activity A does all of the initialization needed for both A & B. All of my local testing on real hardware and emulator, A is always created (onCreate) before B is created.
However, on my app's crash report, I see an exception which can only be explained by B being started without or before A. Is this possible? Will Android create an internal Activity without creating the other activities for my app (B without A)? Is the order of Activity creation guaranteed (A then B)? How would I re-create either of these scenarios using the emulator or real hardware?
I can easily move my initialization code to work regardless of which Activity is started first, BUT I wanted to learn how to reproduce and test before making changes. I looked through the documentation but it didn't really help.
Here is the code that starts task B when user presses "play" button:
private void handlePlayTouch()
{
Intent intent = new Intent(getApplicationContext(), PlayActivity.class);
startActivity(intent);
}
After you started Activity B, you press home button and make your application in the background. The system would kill your application if the free memory is very low. If you tried to switch to your application after your application killed, the system would try to restore your application and activity B without create A first.
You can use DDMMS's Devices view to manually stop your application, there's a red "stop process" button.Make sure that you should make your application in the background.
In your case, I suggest you using a single activity. In the on create, you can prepare everything and then do what you need. If you would like to be sure that something will be executed only when something else is finished, use AsyncTasks.
In doInBackground => do the initialisation and onPostExecute, do what you have to do after.
The onPostExecute will bee executed only when the doInBackground has finished.
http://developer.android.com/reference/android/os/AsyncTask.html
EDIT:
Your structure is not respecting a good programming practice in Android, but if it is mandatory for you to keep this structure, you should at least use "unkillable" services for the activity A. This will make your code harder to destroy as a simple activity when your app will be put on the background, but there is still a chance to be destroyed.
To understand your problem, see the android activity life cycle:
For the services using, see:
http://developer.android.com/reference/android/app/Service.html
http://www.androidguys.com/2009/09/09/diamonds-are-forever-services-are-not/
I am finding it hard to understand the exact circumstances in which each the various launch modes would be used in Android. Could anyone provide me with some examples to help understand when the various modes are appropriate?
Between the Browser and Alarm Clock applications, you cover all four launch modes:
BrowserActivity uses singleTask. There is only one browser activity at a time and it doesn't become part tasks that send it intents to open web pages. While it might return to whatever most recently launched it when you hit back it is actually fixed at the bottom of its own task activity stack. It will share its task with activities that it launches like bookmarks.
BrowserBookmarksPage uses singleTop. While there can be multiple instances of this activity, if there is already one at the top of the task's activity stack it will be reused and onNewIntent() will be called. This way you only have to hit back once to return to the browser if the bookmarks activity is started multiple times.
AlarmClock uses standard. The user can launch multiple instances of this activity and these instances can be part of any task and anywhere in the activity stack. As a fairly simple application it doesn't really demand tight control of its activity.
AlarmAlert uses singleInstance. Only one alert activity at a time and it is always its own task. Anything it launches (if anything) becomes part of its own new task.
The official documentation is a bit confusing so here's a table to help.
http://androidisland.blogspot.com/2010/12/activity-launch-modes-simple.html