Android: Making network requests in a fragment, handling config changes - android

Currently in the app I'm working on network requests are made with ASyncTasks inside of headless retained fragments (references: 1 2) to handle device rotation, etc. It feels pretty hacky (aren't Fragments supposed to be "reusable UI components"?) but works as advertised. So far so good.
The problem now is that I'm modifying the app to support tablets which means converting most Activities into Fragments. Currently the Activities that make API calls try to reattach their "worker fragment" after config changes to see if the API call is already in progress or has already completed.
This doesn't work when an Activity is converted to a Fragment because it would be accessing the Fragment Manager of its host activity - which may be hosting more than one fragment!
After some research it looks like I could use nested fragments (https://developer.android.com/reference/android/app/Fragment.html#getChildFragmentManager()) introduced in API 17 to continue with this approach. To me this feels like it's getting a bit out of hand - there must be a simpler way.
Long story short - what's a simple approach to making API calls from fragments that gracefully handles device config changes? I'd imagine most tablet apps out there do this; so if you've built a tablet app, how do you go about it?

Please look up
Fragment#setRetainInstanceState(true)
this way you can ensure the Fragment is retained across configuration changes.

Related

Sending data from an activity to an object on a 3rd party activity

In the course of creating an android library, I've learned I need to be able to open an activity from a generic library object and have the activity pass back data to the the library object. Normally, I would simply use startActivityForResult and call it a day, but in this case the library object will be using the client application's context. As such, any result would be sent to the client application and not to the library object.
So the flow would be something like this: Client instantiates our library object -> the library object determines it needs to present its own activity and does so -> library's activity returns data to the library object which can continue processing
I've tried a couple of different solutions but none seem to produce the desired results.
fragments - the issue I ran into here is that the fragment is tied to an activity which means it would need to somehow be tied to the client's activity in order for our object to get what it needs. So for our purposes this doesn't make sense to use.
Temporary splash screen - this is the route we're currently leaning towards since a basic splash screen would allow us to leverage our object on an activity we owned which could then call the activities it may need along the way and then return a response to the client's app in the activityForResult. The drawback of this design is that we were hoping to leverage a set of events which the client could code to when we fire them off. However this can be worked around if needed.
Also looked into leveraging the sharedPreferences but the issue there would be that when we returned to the client's activity we'd somehow need to "kick" the library to continue working. We don't want our clients to have to make multiple calls into our library. And spinning off a background thread to "poll" feels like very bad practice in this situation.
So what I'm looking for is whether the 2nd approach is really the only way to solve this or if there is another way in android development which I'm currently unaware of?

Android App Architecture

Let's say I have a simple app consisting of:
A Fragment with a list view to display a list of books
An Activity to hold the fragment
Some web component that will issue a query to a server somewhere to get the list of books to display
What's the best way of wiring these components together? I see a couple of options but which is best (are there any best practices around this)?
Activity issues query to webserver (via AsynTask / new Thread), and pushes results to fragment
Create another fragment without a UI and have this issue the query via AsyncTask / new Thread (like option 1 but will remove the activity being destroyed on screen rotation issues)
Fragment directly calls the webserver, activity does nothing
Add an intent service to do the query and then broadcast results to either:
a) Activity - which pushes them to Fragment
b) Fragment receives broadcasts directly
Are any of these considered a better approach than the other?
Various Fragment related posts have said "consider the fragment a view and the activity the controller" so this would suggest option 3 was maybe not such a good idea.
Option 2 seems a hybrid of considering the activity a controller, kind of delegating some of the 'controller' functionality to another fragment but crucially not the 'view' fragment
Option 4 seems interesting but then you have the issue of having to broadcast all the results (whereas 1 and 2 you will have the actual objects). Granted you could make the broadcasts more efficient (and secure) by using the LocalBroadcastManager but you're still having to broadcast all your web results.
What if I was downloading images (something substantial) rather than (for example) JSON messages that are turned into lightweight Parcelable objects?
As I said, I can think of many ways of doing this - what do we think is the right way?
All your problems can be addressed with Loaders. It's what they were designed for. Check out the dev guide: http://developer.android.com/guide/components/loaders.html

Is it a good idea for a Fragment to delegate all navigation control to Activity?

Inspired by the Android developer guide I am trying to write code in which all fragments are self-contained (in terms of network/logic) and any actions they perform (click/tap) which should result in launching a new activity/fragment would be delegated to the activity (through callback).
To begin with, it seemed right. But now , when I have fragments which have more than 1 such widgets (which need the fragment to navigate to a new screen), it seems like a mess. I either need to write multiple callbacks or do some switch-case logic in Activity for different actions done on a fragment.
If this design sounds bad, what are the scenarios where implementing callbacks (as suggested by the guide) would be a good idea ?
I don't know how you are implementing these callbacks.
One approach to this problem is to use the contract pattern:
The fragment defines a Contract interface, that any hosting activity must implement
When the fragment wants to pass control to the activity, it calls a method on that interface
Jake Wharton has the canonical implementation of this in a GitHub gist. The only piece that is not shown is that the activity that hosts his MyCoolFragment needs to implement the MyCoolFragment.Contract interface.
This assumes that each fragment has distinct events to raise to the activity and therefore needs its own interface. If you have several fragments with common characteristics, you could standardize on a single interface, rather than duplicating the Contract everywhere.
There are other approaches (e.g., the comment on the gist suggesting using a message bus), but for simple fragment->activity communication, the contract pattern should have the least overhead, both in terms of coding and runtime implementation.
Your general approach, though, of delegating work to the activity where that work may result in changes to another fragment, is definitely a good one. It makes it that much easier to handle the cases where the fragments are not on the screen at the same time, perhaps hosted by different activities, as you handle different screen setups (phone vs. tablet, single screen vs. displaying content on a connected TV, etc.).

Android: Intended use of fragments with services, dialogs etc

I've been creating android apps for a few months now and I'm having trouble with the intended use of Fragments.
Fragments are supposed to be reusable UI components but how far do you make them stand alone?
One of the Fragments I've created is a ListFragment of downloadable videos. At the moment I've implemented all the methods inside the Fragment with little or none of the methods calling the host Activity. The Fragment calls the Activity for a few minor things but everything like downloading files and finding them on external storage is done by the Fragment.
90% of the time I find it's the easiest way of implementing it but there's some times it just doesn't work.
An example is a confirmation dialog for deleting a video in my ListFragment. The dialog is a DialogFragment so is attached to the Activity but all the UI update and deletion methods are inside the ListFragment. So I end up with the DialogFragment calling the Activity just to call the ListFragment.
Another example is binding to a Service. Do I bind the Activity to the Service or just the Fragment? The Activity has no use for the Service but is a Fragment supposed to be doing all the work of starting and maintaining a Service? If not it means all the Fragments calls to the Service have to go through the Activity so the Fragment is no longer stand alone.
I'm wondering if I'm taking the stand alone idea too far, is a Fragment instead supposed to be minimally self-contained and actually rely on the Activity hosting it for all the heavy lifting?
Thanks for any help.
A very interesting question!
I usually try to keep my fragments as isolated as possible. That means I usually don't let them know about anything around them except for their own activity. It's then the activity's role (if you ask me) to provide what-ever-is-needed to the fragment.
In practice this means that my fragments never own their own content, like a content provider or a custom DAO. The activity (or - God forbid - the application) owns it and then provides only a subset of the data, like a cursor, a domain object or an adapter, to the fragment.
This also means that when a fragment modifies an item it has to ask the activity to persist the changes. Or if an item is to be deleted, the fragment has to ask the activity to show the corresponding UI for that operation (yes, it's technically possible to let a fragment show another fragment, but I usually try to avoid it as far as possible).
When it comes to services and binding to them I really don't know what to suggest as it really depends on the service and what it's doing. If you're downloading new content from the internet in your service, then it seems rectified to let the activity handle the binding (as it is the activity that needs to save the data, according to previous discussion). If you, on the other hand, are calculating something specific, based on your isolated data (e.g. decrypting a file or so), then it might make sence to let the fragment handle that part.
In an even greater perspective one soon realizes that a setup, such as described above, will give birth to quite some callback interfaces as each fragment needs to establish a contract to its activity. Hence, for smaller projects it sometimes happens that I override my very own fragment-pardigms.
I also can't help noticing that when using fragments, my applications tend to be very MVC oriented in their architecture. I leave it to you and any future readers to decide wether it's a good or bad thing ;-)
Cheers

Fragments, setRetainInstance(true), and threaded libraries

Here, Dianne says that the old methods of retaining objects via onRetainNonConfigurationInstance() are now made obsolete by the fact that you can retain Fragment instances over configuration changes.
And here, in the API Demos for fragments, it shows how to use this method for maintaining threads after a configuration change.
I see that during a configuration change, when the Fragment might not be attached to any activity and the thread is done doing it's work, it's able to call wait() so that it doesn't try to deliver results while an Activity isn't attached. I find this very useful, and a great way to mitigate one of the more pain-in-the-butt problems with Android orientation changes.
However, if you're using a threaded library (an API library that uses a thread executor, for example), where you don't have access to wait() on said threads, how could we use this new feature to our advantage?
How can we ensure that messages won't be delivered while an activity is not attached?
I've been thinking of a way to maybe queue up messages and delivery them when a new Activity is attached, but I wanted to hit up you guys and see if you've already come up with some solutions.
Also, note, I've looked into the LoaderManager API, and it seems like it would be good for data that needs to be loaded when an Activity is shown, but not for something event based, like logging in via a button, etc.
You could get around this issue using a higher level concurrency utility such as a Latch, which you could have all of your threads wait on until the new Activity is attached (just before they try to access the message queue to deliver their result).
Once the Activity is attached, you can release the Latch, allowing all the threads to deliver their results.

Categories

Resources