My app requires the user to go through multiple pages of input (signing up process).
As the user goes deeper into the signup, I have to keep the data intact till the user clicks on "finish". This process involve activity calling sub-activities and those sub activities calling another sub-activity.
The flow is like this: Main -> Sub-Activity (part 1 of signup) -> Sub-Activity (part2) -> Sub-Activity (part 3).
The problem here is, I'm having a low memory warning from the logcat and various processes are being killed as the user goes in deeper into the app. I already tried to save on-hand memory by not passing custom objects among activity but by storing them into mysqllite and retrieving them when needed. One more point to add is, I'm not dealing with images and controls used are just textviews, editviews and spinners.
My question is, is it common to have low memory issues when there are multiple sub-activities chained? How do I go about it to free up memory? Does custom controls uses significantly more memory than preset controls? (One of my hunch)
*Edit* I found the reason for the low memory issues. It has nothing to do with sub activities. The culprit is the custom controls i'm using. I did a test by using the preset controls instead and the overall performance of the app improve drastically. I no longer have the low memory warning and everything works smoothly now.
I dont think it is common to have memory issues with subactivities.. i have used a tab host with 5 tabs and 3-4 activities in each plus complicated methods http calls and image adapters and there were no issues (this way the activites dont call the onDestroy method but just call onPause and then onResume). try having less global variables ex. just reference the views and get their data when you press the next button to pass to other activity or something like that so that the garbage collector collects the trash. remove some of the references when onPause is called and then if you need them again just reference them again (maybe on onResume)
Related
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.
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.
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.
I have developed some apps for Android, and this questions stays always:
How should I structure my UI? Should I launch activity after activity and leave the phone to make the "back" button, or should I choose more optimized, but more complex to implement, way with switching manually Views and then manually doing the "Back" button functionality?
What do you think (or know) is the better practice?
I would say that multiple Activities almost always makes more sense. I just don't think Android is designed for constantly switching its own views - you miss out on so much. You have to implement Back yourself, you don't get any inter-Activity transitions, you have to implement a lot of internal logic to resume an application in the correct state. If you don't partition your app into Activities, it makes it a lot more difficult later on to change the flow of your application. It also results in one mega-Activity that can be a lot harder to handle than a lot of smaller pieces of code.
I have trouble imagining that speed is really an issue; if it is then there's something wrong with the way you're initializing each Activity. For example, I used try to pass Serializable objects between Activities, and that proved to be incredibly slow; when I switched to a faster method of passing objects, the speed of launching Activities increased immensely.
Also, I think it's telling that the Android guidelines for Activity and Task Design don't mention switching Views at all; it's centered around an Activity-as-View design.
I'd like to point out some instances when a single activity might be better design for an Android application that has more than one full screen View:
If the application screens are tightly coupled and share a common Object that they are all operating on. In this case passing around the Object may require a Bundle and can be error prone since there will be copies of it. A good example might be a wizard. Yes you could use static's to access the common Object but static can be dangerous in Android (think configuration changes!)
If you want some really cool animations in between screens. Maybe you want a bird to take off in one screen and land in another screen. Try doing that when each screen is an activity!
On the other hand if one of your screens is designed to be shown by any number of other applications then that screen should be its own Activity.
UPDATE March 2014:
At this point the question should now include the choice of Fragments. I think that Views are probably the least likely choice of the 3: Activity, Fragment, View. If you want to implement screens that make use of the back button then it should be either Activties or Fragments because both handle the back button natively. Fragments will need to be added to the FragmentManager back stack for the back button to work. Managing fragments, dialogs and the back stack can be a bit of an annoyance though!
UPDATE Sept 2018:
Some devs at Google are recommending single activity apps using the new navigation architecture component.
Also keep in mind that implementing your app with multiple Activities will give the user a more coherent experience with the platform as a whole. Part of the experience will be shaped by using the built-in Google apps, so users will probably have an easier time using your application if it behaves similarly to the ones that are already installed on the phone.
Different from others I use a mixture of both, for example,
1. There is a main menu when the application starts
2. You click on search, takes you to search activity
3. Then there's a filter button, which just switches view and shows you filter options
4. There are two buttons at the end of the filter view, You hit "Search" or "Cancel" and you are back to the Search View again (without switching activity)
5. Now if the user hits the phone back button he's taken back to the main menu instead of the search filter options. Which I guess is the correct behavior.
Use it the way user will feel natural. And keeping everything in one activity will make it complex.
It all depends on application, what are you trying to achieve better performance, smoother UI. IMHO I prefer the second approach of controlling the Activities manually even that it is more complex as you have stated. This is a approach I have used in my android tabs project, also you might want to take a look at a class called ActivityGroup (not sure the package) it allows you to have multiple activities that you can switch between, good thing about this class is that your activities are not unloaded when you switch but a bad thing is it takes longer to load your main app.
Just my opinion.
The problem with switching views, that I stumbled upon, is also caused by garbage collector. Seems that GC is triggered when you leave activity and not the view. So, changing tabs with a fairly complex children views, for instance, will almost inevitably lead to stack overflow exception..
I've experienced so many problems with multiple activity layout that I strongly discourage it, unless there's good reason to pick it.
Disadvantage of multiple activities
Using multiple activities it is much hard to refactor code to return data from activity.
If you call a 'sub'-activity then the main activity may be killed. But you never experience that while debugging on a decent device, hence you need to handle always saving state and correctly recovering state. That is a pain. Imagine calling a method on a library (ie. another activity), and you would have to be ensure that when that method returns your app must be able to recreate its state completely with all fields on all objects in the VM (ie. activity.restoreIntance). Its insane.
Also the other way round, when you open a subactivity the VM might have been killed since the subactivity was first spawned, such as when app is minimized while subactivity is displayed.
Its so much cleaner to just have one place to store the relevant app-state, and in my case, most often if VM is killed, I want to return user to main-screen, and let them do their stuff again, because I don't spend 30-50 hours coding save/resume functionality that 0.1% of users will ever experience.
Alternative
Fragments or just manage you activity views yourself. Managing views manually, requires coding some view-switching alternative to activities/fragments with transitions if desired.
And no it does not mean one mega-activity, as suggested in the accepted answer, in any other way than its one mega-app. It just requires a bit more design of the codebase into fitting pieces, because there's slightly more work managing views, though much less work managing activity-state and other weirdness.
Possibly relevant: Reddit: It's official : Google officially recommends single activity app architecture