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
Related
I would like to describe how the communication in my app works in the hopes that someone can tell me if it's good/bad/just okay design.
My app is single Activity multiple Fragments. The Activity has several generic functions such as show/hide a Progressbar animation on the screen or showing a Snackbar. This is functionality that should only be implemented in one place.
My Fragments send broadcasts whenever they need functionality that is not in the Fragment. For example, if the Fragment wanted to show a Snackbar message, I would send a broadcast like this:
localBroadcastManager.sendBroadcast(new SnackBarIntent("Show this text"));
The Activity receives this broadcast, and shows the Snackbar message. Of course, this is a one way message. My Fragment doesn't know if the broadcast was received. But all in all, it works. I can send broadcasts from anywhere, a Service, an Adapter, etc. I can also send Broadcasts between Fragments if I wanted.
I understand there are alternatives to this. There is an EventBus. Or I could pass a reference of the Activity into the Fragment, Adapter, etc. To me this sounds like a terrible idea that could prevent proper garbage collection.
Then there is RxJava where I guess my fragment subscribes to an Observable that I get from the Activity.
But the question remains, is it bad to use BroadcastReceiver in this way? And if so, why?
Is it wrong? No, they were meant for things like this. I'd make sure I was using a local broadcast and not a global one, for efficiency. Some of the alternatives may provide a nicer API or more features, but they all do more or less the same thing.
I would say that unless the part of the code that broadcasts is really buried that you're better off with interfaces and method calls than broadcasts. The problem with any kind of event broadcast is that it decouples the sender and receiver. That can have advantages when you'd otherwise need to pass objects through multiple levels or to places that shouldn't know about that part of the system. But it has drawbacks in maintenance, especially if multiple places can put similar messages on the same bus.
I have application where I have Activity with few Fragments. In that state it's easy. In Activity, using retrofit I make request to REST API, get data then pass it to Fragments using bundle. (Passing list of my objects using bundle was a little pain, but manageable)
Problem starts when I want refresh data in Fragment every x seconds. With described solution I'd have to recreate Fragment with every request, which is ... stupid.
So I have 2 ideas:
make all requests to REST API in Fragment. But I have no idea if it's considered as good solution.
make all requests in Activity and exchange data using EventBus library. (http://greenrobot.org/eventbus/)
Can you please tell me if one of those ideas is good, or should I do something completely different? Or can you tell me pros and cons of different approaches?
Thanks a lot for answers!
Make your fragments loosely coupled with activity so that it can be used with other activities. According to Google -
In order to reuse the Fragment UI components, you should build each as a completely self-contained, modular component that defines its own layout and behavior. Once you have defined these reusable Fragments, you can associate them with an Activity and connect them with the application logic to realize the overall composite UI.
Read more - https://developer.android.com/training/basics/fragments/communicating.html?hl=ru
It is better to request network data from Fragment. Also if you have any dependency of the data in your activity which is received from the network call then you can also use callbacks to send that data back to activity
It's better to have service for HTTP calls. You can make async calls from service, and implement listener interface at your activity or fragment. Than that listener can interact with view.
I usually agree with MmtBkn, but since you use Retrofit, I think it is at least not a bad practice to perform HTTP requests from the UI class. And in my opinion you should make these requests from the Fragment, because it contains the views where the loaded content will be displayed. If you think about placing the Fragment in another Activity, you would end up with duplicate code that performs the HTTP request and sends the data to the Fragment via event bus.
I have to solve a theoretical problem and just want to get feedback about the best pattern / practice to solve this in android.
Task:
An app could have several activities / fragments showing a list of objects. If one object is present in more than one list at the same time, I want to synchronize changes to this object. So e.g. if I delete the object it should disappear in all lists.
The restricts are that
I don't know which lists are currently instantiated
Every list has it's own object instance. Data is not shared directly between lists
My solution so far would be to
define a Storage class which provides methods for data access
create a custom Application class and instantiate the Storage class with the application context (which is needed for e.g. content provider access)
the Storage class defines a Listener where each activity can register itself
if an activity modifies an object, which it has to do through the (Application) Storage, the Storage class sends an event to each activity / fragment registered so they can adopt the changes.
Does anyone know a better solution for that? And is my solution conform with the android lifecycle?
Thanks a lot for every kind of useful feedback
If you want to deal in Object then read up on implementing Services and Binding to them. You can provide all your objects with your own API methods and return values. If your data fits into a data cursor model, then you should read up on building your own ContentProvider. It has data observation built in and all the Adapters support it already.
Your solution seems pretty good. You could use an EventBus like Otto http://square.github.io/otto/ to send an event to all your activities/fragment when an object is modified.
If you insist on maintaining the separate lists in separate Activity/Fragment instances, then you will be prone to lifecycle problems (you might miss an object modification event while you're paused or something). Otto or other EventBus libraries might help.
However, I think it would be much simpler to host all those lists (and their possibly-shared objects) in a local bindable Service. Each Activity/Fragment can then simply bind/unbind to it in onCreate/onDestroy, thus guaranteeing an up-to-date view of those lists.
See http://developer.android.com/guide/components/bound-services.html
Another similar solution would be to host all those lists in a retained Fragment. Using retained Fragments would be simpler than a Service because you don't have to write all the bind/unbind code. However, retained Fragments might not work as well as a Service if you have multiple Activity components that need access to the same lists of objects.
Yet another hacky solution is to just host all those things in the Application instance itself (effectively a global variable). Then your Activity/Fragment code can just call ((MyApplication) getApplication()).getFooList() to get to those objects.
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.).
Im searching to make a simple android app that can do two things:
Show incomming bluetooth data on a graph
Send user defined data back using a textbox and a button
I'm using the navigation drawer, and loosely based on a tutorial, I've set up a GUI with two fragments, each running their own activity.
My question is now, where would I put all the bluetooth related stuff? Each fragment must be able to both send and receive data, will I have to implement the bluetooth connection in each activity? Can I implement it in one activity (e.g. mainactivity) and reach it from the other activities? Is there a better way to do this (i.e. two fragments from one activity)?
Update:
Maybe I'm confusing myself a bit. What I currently have is a main-activity, (extends Activity) that starts one of two fragments (extends fragment) by calling
fragmentManager.beginTransaction().replace(R.id.container,
MyFragment.newInstance()).commit()
So this is actually one activity only, I guess. Question is still, will I put bluetooth related stuff in the mainActivity, or in the fragment-classes that are created. Do I even need the fragment-classes, or can the xml-fragment layouts be handled from within the mainActivity instead?
You probably want to implement a Service, which you can reach from any of your activities or fragments.
Alternatively, you can have a singleton object somewhere which manages this connection, but this can create more complicated lifecycle issues, so I would recommend simply using a service.