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.
Related
I have read the documentation and some other questions' threads about this topic and I don't really feel convinced; I don't see clearly the limits of use of this technique.
Fragments are now seen as a Best Practice; every Activity should be basically a support for one or more Fragments and not call a layout directly.
Fragments are created in order to:
allow the Activity to use many fragments, to change between them, to reuse these units... ==> the Fragment is totally dependent to the Context of an activity , so if I need something generic that I can reuse and handle in many Activities, I can create my own custom layouts or Views ... I will not care about this additional Complexity Developing Layer that fragments would add.
a better handling to different resolution ==> OK for tablets/phones in case of long process that we can show two (or more) fragments in the same Activity in Tablets, and one by one in phones. But why would I use fragments always ?
handling callbacks to navigate between Fragments (i.e: if the user is Logged-in I show a fragment else I show another fragment). ===> Just try to see how many bugs facebook SDK Log-in have because of this, to understand that it is really (?) ...
considering that an Android Application is based on Activities... Adding another life cycles in the Activity would be better to design an Application... I mean the modules, the scenarios, the data management and the connectivity would be better designed, in that way. ===> This is an answer of someone who's used to see the Android SDK and Android Framework with a Fragments vision. I don't think it's wrong, but I am not sure it will give good results... And it is really abstract...
====> Why would I complicate my life, coding more, in using them always? else, why is it a best practice if it's just a tool for some cases? what are these cases?
I am sorry if I wrote too much, and thanks for your time. I hope I will get your attention, because I really need ideas and experiences about this topic.
Best regards, Ahmed
You shouldn't always use fragments. Fragments have their uses, such as when you want to page in and out parts of the screen or when you want to drastically change the UI in different orientations. When they make sense, use them. When they don't, skip them. I find they make sense in maybe about 10-20% of apps- I rarely see the need.
If there's a certain positive aspect apart from the simpler reuse of logic through different layouts, it's the ability of Fragments to be kept alive by the system at orientation change, aka while an Activity is reconstructed from zero, a Fragment can retain its instance, and therefore using them is more stable than an Activity. Also, switching between Fragments is quicker.
Personally, if I don't need to mess around with different orientations and layout sizes, I still prefer using Fragments and a singular container Activity around it, for stability and seamless switching between the different screens.
Its quite a general question and not directly related to a specific programming problem. But in my opinion good software is based on good design and therefore a good understanding and best practices. So your question is a good one for stackoverflow.
So, what about fragments. It took me a while to understand why you could or even should use them. As #pskink said, you can easily live without them. But if you are planning to rollout your software on different devices, you should definately think about fragments.
The screen resolution and density is not the only problem. Think about a smartphone. The screen is much smaller, so you can not present your app the same way as you can on a tablet. For instance a master detail flow. Left side, a list of elements and when you click one element, you will see details of that element on the right side. Easy to do on a tablet. But on a smartphone you would put the master-view into one fragment and the detail-view into another one.
You got two options to realize that scenario. Either programm different activities for smartphone and tablet but because they are actually doing the same logic, it's better practice to put the logic into fragments and reuse those fragments in two layouts (phone/tablet).
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.
This is actually a very simple thing: I need to know if there is any of MY activities in the history stack? I'm not talking about other apps, just my own app. And I don't even need to know what are they or how many of them, I just need to know IF THERE IS ANY? Is there a way to achieve this? (ActivityManager.getRunningTasks().topActivity() is not for this purpose.)
(I'm implementing a backward/forward feature, as seen in many browsers. At first I tried to manage my own history stack and not use Android's at all. So I used noHistory=true for all activities in the manifest. This leads to the problem that the app's behavior is weird when it comes to the interacting with other apps or the Launcher. Now I tried to utilize Android's history stack for Backward operation, but my own stack for Foreward. But then it hits an unexpcted problem. .... Not just that, there is this security consideration in the app so that I can't let the user go back to any activity if the file has been locked up. I have to have total control over the stack.
Having been bothered by Android's activity life-cycle model and the history stack for several days. Extremely inflexible. How can they assume that all applications all activities in the world behave in the way they imagined in the lab!!!??? Seeing lots of people asking questions on the Internet in this area, and it seems to me everybody hit a dead end and then try to find some work-around, or compromise, or might as well change the spec. Android has been around for 3 years now, but they still didn't do anything to make it more flexible. I guess it must be a very fundamental thing in the design since Day One so that they know about the problem, but they can't do anything about it. Call it a wrong design.)
(And this non-blocking, non-synchronize dialog/message boxes. I don't know how they come up with this design. Whenever you want the user to confirm something, you have to break the program flow into several parts. This undoubtedly makes the program difficult to write and impossbile to maintain! If you have a series of questions one dependent on another, you might as well limplement a state machine.)
If you use Fragments in SDK level 11 and higher (so Honeycomb and certain Gingerbread levels), you can explicitly manage the stack. For regular Activities, you really don't have access to the stack, so you're out of luck there. You could possibly implement a personal stack using an application-level stack: storing the Intents you're using to launch Activities so you can move forward and then returning another Intent with the configuration data for each Activity (when each Activity finish()es you pass this state in the onActivityResult call back).
It would be very messy though.
Since you create and finish the activities, you should be aware of what is on the stack at runtime. Generally, you can control the stack pretty well. Take a look at the ApiDemo revolving around manipulating the stack.
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.
This pattern is similar to the pattern Main Servlet (the Front Controller) that is used for developing web applications.
The main idea of this pattern: we have one Activity that manages multiple views and this activity is responsible for representing current content. Not all views need functional of activity (e.g. life-cycle methods) so the main question is: if I can go without activity why do I have to use it?
I have found the following disadvantages of using this pattern:
Official source doesn't recommend to Overload a Single Activity Screen
but they don't explain why.
We cannot use TabActivity, ListActivity, MapActivity. But there are some tricks to go without them.
If different screens have different menu it's a problem to make that without activities.
It is necessary to keep history by ourselves. But it's not so difficult to develop.
I have found the following advantages of using this pattern:
It's faster to change the content of current activity than to start another activity
We are free to manage history as we want
If we have only one activity-context it's simpler to find and solve problems with memory leaks
What do you think about this pattern ? Could you provide any other advantages/disadvantages ?
We cannot use TabActivity, ListAcivity, MapActivity. But there are some tricks to go without them.
You have to use MapActivity if you want to use MapView. You have to use PreferenceActivity if you want to use preference XML.
It is necessary to keep history by ourselves. But it's not so difficult to develop.
The difficulty in managing your own history will depend greatly on what the history needs to be. Implementing history for a simple wizard will be fairly easy. However, that is a particularly simple scenario. There is a fair amount of history management code in Android that you would have to rewrite for arbitrary other cases.
You also forgot:
#5. You will be prone to leak memory, because you will forget to clean up stuff, and Android will not clean up stuff (since it assumes that you will be using many small activities, the way they recommend).
#6. Your state management for configuration changes (rotation, dock, SIM change, locale change, multiple displays, font scale) will be more complicated because now you also have to figure out what extra stuff (e.g., history) need to be part of the state, and you have deal with all of them at once rather than activity-at-a-time.
#7. Having multiple entry points for your application becomes more challenging (e.g., multiple icons in launcher, app widget linking to some activity other than the main one, responding to etc.).
It's faster to change the content of current activity than to start another activity
For most modern Android devices, the speed difference will not be significant to most users, IMHO.
If we have only one activity-context it's simpler to find and solve problems with memory leaks
Except that you still have more than "one activity-context". Remember: your activity, large or small, is still destroyed and recreated on configuration changes.
What do you think about this pattern ?
Coase's "nature of the firm" theory says that businesses expand until the transaction costs for doing things internally become higher than the transaction costs for having other firms do the same things.
Murphy's "nature of the activity" theory says that the activity expands until the transaction costs of doing things internally become higher than the transaction costs for having other activities do the same things. Android developers will tend towards a "user transaction" model for activities -- things that are tightly coupled (e.g., steps in a wizard) will tend to be handled in single activity, and things that have little relationship (e.g., browse vs. search vs. settings vs. help vs. about) will tend to be handled in distinct activities.
This will be horrible to maintain if new functionality is added later on.
I'm also not convinced it will be so much faster that the user could notice.
Having components as smaller pieces that are easier to change or swap out is definitely the way to go.