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
Related
I have a fragment with a list view on it, and the user is able to select items in that list. Whenever at least one item is in a selected state I would like to reveal a "delete" toolbar button on the parent activity. Would I just raise an event from the fragment to achieve this?
What about doing the deletion - should the activity or the fragment be responsible for this? Either way the activity would need to somehow ask the fragment to either do the deletion, or ask it to reload the list (if the activity does the deletion).
Really looking for best practices for this kind of activity/fragment communication, and to reduce the coupling (presumably interfaces will play a part too).
For a second (related) question, my fragment is currently responsible for retrieving the list's items from the database, but in a book I've read they show the activity doing this instead, which then passes the items to the fragment. What are the pros and cons of each approach?
As an answer to all of your sub questions, keeping the classes loosely coupled and linking them using an EventBus is the ideal way to go for!
EventBus allows publish-subscribe-style communication between components without requiring the components to explicitly register with one another (and thus be aware of each other). It is designed exclusively to replace traditional Java in-process event distribution using explicit registration.
This seamlessly allows you to pass data as event to multiple classes and listen to those events from multiple other classes as well. To see the usage, see this Answer
There are lot of threads about how to make two Fragments communicate each other using an interface and event call back methods through Activity.
Is there any specific reason to do that way? or is there any downside doing this way-directly calling method of fragment-2 from fragment-1
((Fragment2) (getActivity().getFragmentManager().findFragmentById(R.id.fragment2))).methodOfFragment2();
Unfortunately the activity-interface in many tutorials doesn't give people a good model for actually making their fragments modular.
What most people end up doing is making their activity-interface some central repository for hardcoding relationships between fragements. Thus, when I first started usnig fragments and read about this "model" I too wondered at its value, since I was just introducing a layer of indirection over my fragment relations.
overtime I learned or adapted patterns, like the Broadcast/Receiver model to my fragments. Now my fragments don't communicate through the activity-inteface, but instead broadcast events on an event-frequency with payloads through a local broadcast object, and other objects interested in those events can register to receive those events and data.
In other words, my fragments have events, and they publish those events, often with payloads, and other objects can register to receive notification and data from those events. If no one's listening, nothing happens. If I write some new object that want's to receive data from the event, my other fragments and even my broadcaster don't need to be aware of any specifics of how my new object was implemented.
If you want to learn more about the broadcast Receiver model Android has its own LocalBroadcastManger, or you can write your own lightweight one, and you can find some tutorials on how to use it here:
http://developer.android.com/reference/android/support/v4/content/LocalBroadcastManager.html
how to use LocalBroadcastManager?
Because a fragment is suppose to be able to be reused. If you are calling a fragment that exists in one instance of your app and you reuse one of those fragments in another section of your app but not the other then guess what you just broke your app trying to call something that is not there.
Fragments should not know another fragment exists which is why all communication should go through an 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.).
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
I'm going through the tutorials for android and something about intent/activity interaction is confusing me. In Javascript whenever there is an ajax call we define how the results should be handled along with the ajax call and we can use different callbacks for different ajax calls throughout the application lifecycle. In android starting an activity with an intent and handling the passed back results are decoupled, at least that's how it's done in the tutorial and there is only a single point of entry for how the results are handled so it's hard to perform on the fly handling of results without messing with the main entry point. I can easily imagine some complex logic that could make the switching inside the main entry point into a horrible mess. Is this a fundamental android architectural thing or is there another way to do things with actual callbacks instead of switch statements in a single entry point?
It is true that you are limited to a single location for receiving responses that an activity has finished. It would be nice if you could define a callback function for each, but that is not how it works.
In my experience though, you seldom have so many different destinations from a single activity that it is hard to manage. Generally each page only leads to one or two other pages that you might care about getting results from.
You can do something like the following to cleanly separate your logic for each case:
void onActivityResult(int requestCode, ....) {
switch(requestCode) {
case Activity1:
onActivity1Result(...);
break;
case Activity2:
onActivity2Result(...);
break;
}
}
Intents and Activities are designed to allow developers to develop re-usable, loosely coupled components.
I understand that, when working internal between two activities that you are creating, the mechanisms can seem unnecessarily restrictive. The restrictiveness is part of the open nature of the platform. The same mechanism that you use to start an activity you own could start an Activity created by another developer or by the OS itself.
That being said, there are a plethora of options for passing information between activities. It really depends what you are trying to accomplish. I try to think of activities just that, activities from the users perspective. I'm going to list some mechanisms for passing data and, if you'd like to further describe your application or need, I'll try to help you narrow the options down:
Intent.putExtra
startActivityForResult (I'm assuming you know this one)
SharedPreferences
Service
ContentProvider
Also note that you do not have to start a new activity for a background process without its own screen such as an Ajax call - you can use AsyncTask instead which allows for a javascript style callback.