In our application when a user switches between modes (different user/ different type of screen) the activity recreates itself (by an explicit call to recreate() ). This behavior was added by a external programmer we hired. He states this is completely normal to do.
The problem I have with this is that 99,9% of all activity state is the same. But when the activity is recreated all data is queried again, consuming quite a bit of time.
Is this a normal pattern? Or is it just as good to only change the data to suit the new situation?
To me it seems kind of strange to manually recreate the whole Activity just to reload some data. In any case just updating the data which has actually changed seems like a much better approach. Especially if you say that it takes quite a bit of time to reload all the data.
The only thing I can think of right now which requires to recreate the Activity is changing the locale or something like, but even that I would not recommend unless it is really necessary. If you are not dealing with configuration changes, e.g. locale, there is no reason to recreate the whole Activity just to reload some data.
I would say it's "normal" in the sense that Activities are recreated all the time by the system, so this just adds another event in which that would happen. Though this is, on it's own, really weird way of going about it. A better, more efficient, cleaner way would be to swap out Fragments on "mode change". You can have a UI fragment for each "mode" and the data stored in a retained Fragment that each one pulls from. This would also help in the sense that the UI doesn't have to be recreated completely with each Fragment swap.
However, if you must, it is an absolute requirement that you follow the same data storage/retrieval methods that you would if the system was killing and recreating the Activity. See How to save state during orientation change in Android if the state is made of my classes?
Basically, you shouldn't be recreating data you already have.
Related
I have gone through different posts and questions for handling rotation and AsyncTask. In each post it is mentioned that using android:configChanges
is a bad practice. But i didn't find the actual reason why it is discouraged and why it is a bad practice. What are the disadvantage if we use android:configChanges to handle orientation.
Note:
I know it is already answered how to handle orientation and AsyncTask. but I want to know reason behind not using android:configChanges.
Well, you need to remember that an Activity can be restarted for multiple reasons.
For example, one of these reasons is when your app is in the background and the OS decides to kill it (with your Activity, of course) to reclaim memory.
When you return to your app, the OS will try to recreate your Activity as you left it, but will fail to do so, because you decided not to bother with it, just used android:configChanges in your Manifest.
If you make sure your app can recover properly from a restart, android:configChanges might not be necessary at all. Because of this, the need to use android:configChanges might indicate some flaw in your app, that may worth to take a look at.
It's not bad practice to use android:configChanges, but it pretty easily can be, if you don't understand exactly what you're doing.
To sum up all what i got form #user13 answer and other stackoverflow questions and blog posts i would like to share my finding to clear some very important aspects.
(user13) It's not bad practice to use android:configChanges, but it pretty easily can be, if you don't understand exactly what you're doing
Using this technique prevents you from easily using configuration specific resources. For instance, if you want your layout or drawables or strings or whatever to be different in portrait and landscapes, you have to manage it yourself if you use android:configChanges.
You need to override and use onConfigurationChanged() method to perform specific action if you decide to use android:configChanges
As user13 mentioned Activity is recreated not just due to orientation change but there are multiple reasons due to which activity can be restarted. Therefor activity restart should be handled for all causes. using android:configChanges only handles one case and there will be unhandled cases of activity restart which will cause a potential bug.
There are multiple and better ways to handle activity restart and plenty of help is also available on stactoverflow so android:configChanges should be used as a last resort according to documentation.
Using android:configChanges is good practice if you know what you are doing.
Just always test how your application how it behaves when it is restarted by system to stay comfortable for user so some state has to be saved all the time but not all.
With config changes like this:
android:configChanges="locale|keyboard|keyboardHidden|orientation|screenLayout|uiMode|screenSize|smallestScreenSize"
Your application will restart rather rarely on new devices that have a lot of memory. If it restarts it's not so unexpected for user anyway, as user had attention elsewhere and came back to app. User don't have to be in exact same state after restart if it happens by manual killing of application or application restart because of some other heavy tasks (playing game) user is doing, the user experience is important here.
If you need to refresh List just for different layouts for orientations changes or you need to hide some view elements you can call:
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
_list.reloadData();
_editorButton.visible(isPortrait());
}
(I use my custom classes but you get the point)
Preface - The code I have created so far already delivers the desired user interface, my question is about phone resources and whether there is a 'better' implementation. Also, I am relatively new to Android development and may be misunderstanding some basic concepts.
I am developing an app with tabs, and some of the tabs have multiple views. At the moment each view is managed by a fragment, and when an user is on a tab and opens a new view, the views transitions horizontally.
(the app is a port to Android of an existing iPhone app, and while the people I am working for readily understand the need to make an Android app as Android-native as possible, they want the basic user interface and control to remain the same so that if an iPhone user buys an Android phone and purchases another copy of their app, there will be no fundamental difference)
The primary tab is different however--it reloads itself. The app is essentially a study aid; imagine that each view is a card representing information, and the user if flipping through cards.
This is accomplished by having the 'card' fragment request that the fragment manager detach and then re-attach itself. This is accomplished by calling a method in the FragmentActivity that executes the following (simplified from the actual code):
FragmentTransaction ft = .... .beginTransaction();
ft.setCustomAnimations(int out,int in)
ft.detach(relevantFragment);
ft.attach(relevantFragment);
ft.commit();
.... .executePendingTransaction();
where 'out' is fromXDelta="0", toXDelta="-100%"
and 'in' is fromXDelta="100%", toXDelta="0"
Consequently, the old view slides out to the left, while simultaneously the new view slides in from the right.
This works just fine, in fact in terms of user experience it is exactly what I want. However, the fragment we are reloading has an extremely complex view hierarchy and my understanding of fragments is that the entire thing is going to be garbage collected and re-instantiated on each transition, which the user may easily invoke a large number of times (100+) while using the app to study.
Almost all of what I have read indicates I should avoid heavy object creation/collection as it will cause my app to devour an user's battery, regardless of whether processor is strong enough to perform without any visual lag.
.
ACTUAL QUESTION: Is there any way to emulate this kind of behaviour that does not force the phone to fully destroy and re-create the view every view seconds as the user clicks through?
Things I have considered:
Eliminate the transactions/animations and simply have the fragment load new information. This would be easy of course, but is not what my employers want.
Create two identical copies of the view hierarchy in the XML, and toggle them back and forth from View.VISIBLE and View.GONE, using a custom ScaleAnimation to attempt to emulate this behaviour. I'm not sure whether this would work, but at first glance it seems rather... sloppy.
This is an unnecessary and/or silly optimization that I should not be worried about, due to how the phone and/or Android system operates, and I simply don't realize I am wasting my time.
Any advice, suggestions, or clarifications on how the operating system work are much appreciated.
my understanding of fragments is that the entire thing is going to be garbage collected and re-instantiated on each transition
If you look at your code, this is impossible, at least at the fragment level. You are not letting go of the Fragment object, nor are you supplying some means for Android to create a brand new identical fragment. Hence, the Fragment will not be garbage-collected.
It is conceivable that Android will call onCreateView() again for your fragment and discard the old views, though that seems unlikely. You can test this by setting a breakpoint or adding a logging statement.
Almost all of what I have read indicates I should avoid heavy object creation/collection as it will cause my app to devour an user's battery
Done millions of times, definitely. Done "100+" times, it will not "devour" the battery. Nibble, perhaps.
Things I have considered:
I would focus on #3. At most, determine if indeed the fragment's view hierarchy is being recreated, in the form of multiple calls to onCreateView(). If it does, then use Traceview to determine exactly how much time this operation is consuming.
To summarize the discussion with CommonsWare in the comments above (and subsequent investigation of ways to address the matter), this is not a productive optimization. Preserving the view hierarchy for reuse, rather than allowing it to be destroy and recreated, only saves a few milliseconds of of CPU time. The vast majority is consumed by the phone's rendering of the views, not their instantiation.
CommonWare is correct in his initial answer (mostly). The Fragment.onCreateView() IS called every time a fragment is attached, but there is no productive way to optimize the view rendering. Nothing to be done, nothing to worry about.
I have an android app that has to load very large files on start up. any time it switches orientations, it has to destroy and recreate the activity, causing the large files to reload. this takes about 30 seconds, this is pretty inconvenient if I were to actually publish this. I am sure that I am doing something wrong here. I have heard of onSaveInstanceState() and onRestoreInstanceState(), but I have no idea how to use them. does any body know how I could use this to speed up the Orientation change?
Use onRetainNonConfigurationInstance() to pass your data from the old activity to the new activity.
Or, store the data in a static data member (but be careful about garbage collection).
Or, store the data in a custom Application object (as Reto Meier suggests here).
While #foxx1337 suggests android:configChanges="orientation", not only is that answer incomplete, but it is not recommended practice.
Start with android:configChanges="orientation" in your AndroidManifest.xml. Also have a look at Activity restart on rotation Android.
hey people,
I have almost finished writing my first android app. It is a note taking app with add, edit view screens etc...
Initially I was handling moving between screens in a single activity by creating new layout objects such as tables etc... and displaying them.
However after some more reading I have changed my method of moving between screens by using different activities for different screens. However each activity that is called as an intent retrieves a large number of variables from the main activity via setExtra and passes back a large number of variables as well.
Now I want my app to be as efficient as possible and I personally think that handling it all in one activity is less memory hungry and processor intensive although this has the negative of meaning variables are always present (and consuming memory) unlink in a separate activity where they are killed on finish().
But you guys are more knowledgeable then me so what do you think is the best way to do it?
If you launch a new activity for the new screens then you will add that activity to the stack. That way a user can press back and get back to the previous activity. Just changing the layout removes this functionality. I doubt very much you'll have performance issues either way.
Best practice would be to start a new activity, best performance might be to use your current approach.
All your activities will reside and run from the same process. So there is no reason you need to pass around a pile of variables. You could (for example) stick them in a singleton which represents your context. When one activity hands over to another it fills in the singleton and the next one picks up its data from there.
Of course if you ever intend an external activity to interact with your ones you may have to rethink this approach, but I think you'd be fine to keep your views as separate activities. Even if memory is ever so slightly higher, I think it's better to do things correctly and only worry about optimization if and only when it becomes obvious you need it.
I am working on an application that tries to streamline data entry from a very repetitive process:
Enter some details that require full-screen graphics and would be confusing if scrolled
Enter some more atomic details
Enter yet more atomic details
Apply the accumulated data
Go back to step 1
I am pretty sure that i can represent this as 3 separate Activities and then just fire up new Intents for each activity in each cycle. What I can't yet get a sense of is whether this is a viable approach.
Question 1: If I do a fire-and-forget approach, how much of the resource management is going to be handled by Android? Will it just happily deallocate/reuse/etc. activities behind the scenes? Or is this something i have to manage myself?
Question 2: Is there a way to cause the reusing of activities so that only one instance of each activity is ever allocated and is just reused for each cycle?
Question 3: Can one manipulate the activity stack so that there aren't ~100 (approximated number of expected cycles) cycles worth of activities on the stack? I'd like to be able to use the back key no more than three times and exit out of the data entry portion to a summary page.
Question 4: Can anyone suggest alternate approaches to the cycles of activities problem? I have considered view flippers and tabs, but wasn't sure that would be better or not.
Will it just happily
deallocate/reuse/etc. activities
behind the scenes?
Yes.
Is there a way to cause the reusing of
activities so that only one instance
of each activity is ever allocated and
is just reused for each cycle?
Try FLAG_ACTIVITY_REORDER_TO_FRONT on your Intent to launch the activity. Based on the docs, it should give you your desired behavior.
Can one manipulate the activity stack
so that there aren't ~100
(approximated number of expected
cycles) cycles worth of activities on
the stack?
100? You must be expecting some very patient users.
Regardless, FLAG_ACTIVITY_REORDER_TO_FRONT should cover that too.
Can anyone suggest alternate
approaches to the cycles of activities
problem? I have considered view
flippers and tabs, but wasn't sure
that would be better or not.
Tabs aren't great for things where you're trying to enforce a flow, since tabs are designed for random (not sequential) access. ViewFlipper/ViewSwitcher could work, though then you have to manage BACK button functionality and make sure you're not effectively leaking memory within the activity, since you're expecting people to be using it for an extended period.