Is it advisable to create your own Activity stack (which contains only the activity names rather then the complete activity as in the default stack) to improve the memory consumption of the application.
What im basically doing is maintaining a string stack containing the activity names and override the back button functionality to launch Intent with the stack top and finish the current activity. I also add a parameter to decide if the current activity should go into the stack or not (useful in certain situation). So basically I do a startActivity every time I have to launch a new activity and finish the current one so that there is nothing in the default stack and on back press also start the activity from my stack and finish the current activity.
Ques 1: Is it advisable to do it this way? What are the possible problems that could happen?
Ques 2: Can someone give me an idea of the memory usage of the default Android activity stack so that I can compare it with my own implementation?
Is it advisable to create your own Activity stack (which contains only the activity names rather then the complete activity as in the default stack) to improve the memory consumption of the application.
Generally no, no more than a Web app typically hacks into the browser to change the browser history and delete items out of the browser cache.
What are the possible problems that could happen?
You lose your state on every operation. Normally, the BACK button takes the user back to the previous activity, with its state intact. There's even a framework for maintaining this state (onSaveInstanceState()) if Android elects to close up an activity to free up memory.
You also force more garbage collection than is necessary, by finishing activities that the user is not yet done with and forcing their re-creation, which wastes CPU time and battery life.
I have some nagging concerns about the impacts of your strategy on configuration changes (e.g., rotation, dock), but I can't put my finger on any specifics.
Can someone give me an idea of the memory usage of the default Android activity stack so that I can compare it with my own implementation?
You are asking the wrong question. The question you should be asking is: What is the evidence that there is a problem in the first place?
It is entirely possible that there is something rather unusual about your application that makes your strategy a sound one (e.g., lots of memory-intensive bitmaps). However, in general, unless there is a demonstrable problem, things like what you are doing fall under the heading of "premature optimization". Even then, there may be better solutions to whatever the actual problem is...but you won't know that unless and until you determine there is, indeed, a problem.
Related
We have an application, with links to various screens and reports.
On a web browser we can navigate to different pages and the pages are added to a navigation history, but I don't have to think about the back stack. I just assume that if the history is taking too much memory, the browser would trim browsing history as needed - But it sounds like in Android we could see out of memory errors if the stack is too big?
What should I do to keep the memory footprint of the back stack reasonable but let people navigate around the application and maintain a history of their past several screens? Is there a setting I should be looking for? Or just a little code script I should be running?
I'd like to use whatever Android natively offers rather than trying to create something from scratch here...
Or am I thinking about the problem the wrong way?...
Don't bother yourself. If system needs more memory it will destroy background activities and recreates them again when user will return to them.
Documentation:
When the system stops one of your activities (such as when a new activity starts or the task moves to the background), the system might destroy that activity completely if it needs to recover system memory. When this happens, information about the activity state is lost. If this happens, the system still knows that the activity has a place in the back stack, but when the activity is brought to the top of the stack the system must recreate it (rather than resume it)
I'm developing Android application where I'm switching between activities.
But I grasp several problems:
If I'm starting new Activity then clicking on the "back" button in my smartphone I'm returning to the pervious activity. But what if I want to make my application be closed by clicking on that "back" button from the new activities and not returning to the pervious? Is it possible to terminate my application from the new activities by the way I'm asking you?
As I understand all activities which were created by the method StartActivity() are holding at the RAM memory of my device. I also don't want to hold all them in the memory space. How can I set some activities not to hold in memory and make them free from the memory space, and what is the best solution for keeping required activities moves (for the history) and for the deleting from memory space the old activity?
The simplest way, as I understand your question, is just to call finish() on those Activities which you don't want to keep. This will destroy them, removing them from the stack and from memory.
However, I wouldn't worry so much about memory here as I would worry about your user's experiences. Don't remove these Activties simply for the purpose of conserving memory. Do it because they aren't needed and when the user presses the "Back" button they don't expect to see them.
I read somewhere that each time you call startActivity() to transition to a new screen, you are creating a new instance of that activity. This immediately raised a red flag to me.
In search of a way to prevent this issue, I read about using FLAG_ACTIVITY_REORDER_TO_FRONT. However I'm a little alarmed that this method is not used in any of the tutorials I've seen for opening a new screen in your app. So I think I might be missing something. I mean wouldn't you always want to make sure you're not creating a duplicate Activity? isn't this kind of a big deal and shouldn't tutorials address it?
I just want to make sure that I am understanding, and dealing with, this issue correctly, and using the commonly practiced way to transition between screens.
I understand in some cases you open a screen, do something, then close it using finish() and go back. But if an app has a complex 4 level hierarchy , and the user needs to be able to jump around between the screens?
I mean wouldn't you always want to make sure you're not creating a duplicate Activity
Most of the time you probably won't want to have two instances of the same Activity but I suppose there are situations where someone might
isn't this kind of a big deal and shouldn't tutorials address it
It is definitely something that Android developers need to know about and understand how to use. I would imagine that you may not see a lot of it in tutorials because most of them teach you the basics to get you started. When a developer is new to Android, they typically have enough to learn about the framework. And they normally show you how to do a few screens (which is often all someone may need). They expect you to learn more of the details by reading through the docs and using websites such as SO
I understand in some cases you open a screen, do something, then close it using finish() and go back. But if an app has a complex 4 level hierarchy , and the user needs to be able to jump around between the screens?
Yes, a lot of times you won't be getting too deep because the deeper the easier it is to get a "lost" feeling. This is why I like using Activities with a Dialog Theme when possible. It gives the feeling that you aren't actually leaving the screen you are on. However, that doesn't really answer your question. There are many flags that can be used with Intents to keep the stack from growing. The one you mentioned works and I also use Intent.FLAG_ACTIVITY_CLEAR_Top quite often if I need to clear all Activities from the stack and get back to one single Activity. There can be so many different situations between apps, users, and developers that how you transition and work the flow or navigation just depends on what you (really, the user) needs.
It seems like you are on the right track by asking these questions. Think about what will give the user the best and most natural experience and find the right flags in the Intent Docs for your situation
I hope this cleared things up for you a little. If you don't understand something, feel free to ask
You usually want to avoid creating a duplicate activity, and IMHO, it's a bug in the Android system that the default behavior is to allow it.
(Sometimes you do want to allow it, e.g. you've written a "get filename" activity, and more than one application is likely to call it.)
You control activity creation in two places: In the manifest, and in the flags of the intent that launches it.
In the manifest, the <activity> tag has the attribute android:launchMode, which can be one of:
"standard"
Default. Can be instantiated multiple times, can belong to any task, and can appear anywhere on the stack. Normally part of the task that called startActivity() unless the FLAG_ACTIVITY_NEW_TASK was used. A new instance of the class is created to respond to each new intent.
"singleTop" Identical to standard, except that if the target task already has an instance of this activity at the top of the stack, a new activity will not be created. Instead, the existing activity will receive a call to onNewIntent().
"singleTask" There can be only one. It's the first activity of a new stack, and is thus the root of an activity stack. If there are more intents, they'll be sent to onNewIntent().
"singleInstance" Identical to singleTask, except that it's the only activity in its stack. If it tries to launch a new activity, the new activity will start a new task. Same as if FLAG_ACTIVITY_NEW_TASK was in the intent.
I personally find the history back stack in android more confusing than helpful to end users. The use of back buttons can often not do what the user expects.
There are a few options available to you if you want to use activities as the main construct.
For workflow type activities (e.g. capture forms) start the first activity with Intent.FLAG_ACTIVITY_NEW_TASK and at the end use FLAG_ACTIVITY_CLEAR_TASK
For top level activities that are often a returning point start the activity with Intent.FLAG_ACTIVITY_CLEAR_TOP. This basically checks if the activity is already somewhere in the stack and if it is pops off every activity above it in the stack and resumes the original activity.
Another possible method for the top level activities is to use one top level activity and use fragments for moving around, e.g. tab browser etc. Then just use activities for actual separate tasks.
In my app there is the ability to have an endless activity stack. The scenario is that you start on one user's page which has a list of people that are "friends" of that user. You can then click on a friend to go to their page, which looks just like the previous one, where you can then click on another friend to go to their page, and so on...
The big problem I am facing is an endless native heap. I believe I am adding to this heap everytime a view is inflated. After a few iterations of this, I am getting OOM errors consistently, so I have to find some kind of solution. The trick is, I want to maintain the last few activities at minimum for navigating some history.
The best I can come up with is monitor the activity stack, and then start finishing activities when it reaches a certain point. Does that sound like a solid approach, or even further can anyone point me to an implementation of that or another approach?
Thanks
edit:
The stack is very simple. Click on a listrow (a friend), go to their page. This is using a normal startActivity call with an intent to the same page you are on, and an intent extra with the user id that will then call the database or a remote api call to get the user's data.
Also, to follow up about Dalvik vs Native, I am routinely checking the meminfo dump during my navigation. I am keeping the dalvik heap as small as possible, cleaning out resources in onStop. The native heap grows much quicker. I have no hard references to bitmaps anywhere, but quite a few drawables on the screen from inflations. Would these drawables lead to android killing my activity eventually? As best I can tell they just lead to OOM without any of my activities being destroyed preventatively.
If I could manually destroy my activities instead of just stopping them (as Android claims to do when low on memory), and keep the destroyed activity on the stack with the state saved, that would be ideal.
edit again:
another key is that these activities will have other activities mixed in with them e.g.
user -> user -> activity a -> user -> activity b -> user
so that is why I want to make use of the built in stack, so I know when I have to go to a user activity and when I don't.
how about making this activity singleInstance, intercept KeyEvent.KEYCODE_BACK, build own back button stack for this activity
i made some example here:
http://esilo.pl/selvin/endlessactivity.zip
I don't think the OOM problem you are experiencing is related to the number of Activities you have open. Android should be destroying any old activities in the background as memory pressure increases. These Activities will then just be re-created when the user returns back through the task stack.
Have you used a tool like MAT (memory analyzer tool) to examine what you have allocated during the runtime of your application. I suspect that you may have a memory leak, or that yo may have to be smarter in your memory allocations.
Does anyone know of a way to show another class without creating a new instance?
It seems a bit crazy from a memory management point of view that each time you want to display a different form / page you need to use StartActivity which then creates a new instances of the class instead of reusing instances previously created.
Thanks in advance
I guess from what has been said - there is no real way to do it which won't hinder the "Back" functionality of the OS?
I'm building an app which is linear except on each screen it has a home button which then makes it possible to countermand this functionality and end in a loop - is there anyway you know of to destroy all over views and reset back to the main class? (IE prevent a memory leak from becoming a problem but also not damaging OS functionality)
Consider it a "clear history" without restarting the app
Not sure if this would work for Android (coming from a MS/C# background), but conceptually one option is to iterate through open forms looking for one with a specific handle. Then, once you find it, simply call the method to show that form. This would depend on there being a Java equivalent to the Application.OpenForms property in .NET.
It seems a bit crazy from a memory management point of view that each time you want to display a different form / page you need to use StartActivity which then creates a new instances of the class instead of reusing instances previously created.
Tactically, you are welcome to add FLAG_REORDER_TO_FRONT to bring an existing activity back to the foreground, so long as you understand the ramifications from a navigation standpoint.
However, your question is rather curious. How are you accessing StackOverflow?
Clearly it's not via a Web browser. Web browsers use the exact mechanism that you feel is "crazy", rendering Web pages even if that Web page had been viewed previously. They have been doing so for over 15 years, and we've been doing OK by it.
The Android navigation model is designed to approximately mirror that of the Web:
Users click on things to move forward
Users click on a BACK button to move to the previous thing they were looking at
Users click on a HOME button when they want to switch to some other major thing to go look at
By "reusing instances previously created", you're circumventing that navigational model. For example, let's suppose your activity stack were A-B-C-D, and you call startActivity() with an Intent for B and FLAG_REORDER_TO_FRONT. Now, the activity stack is A-C-D-B. When the user presses BACK times, they no longer are on the B they were looking at originally, but are back at A. In a browser, this would be rather strange behavior.
There are other flags on Intent, or attributes on <activity> in the manifest, that offer "reusing instances previously created". However, they are not there "from a memory management point of view". They are there where the traditional Web BACK-heavy navigation pattern does not fit your needs.
Assuming you aren't screwing up anywhere, Android will destroy under-utilized activities, garbage collect that memory, and even return that memory to the OS.