I'm implementing fragments in my app. Referring to this documentation,
there is written I should use getActivity() to access activity methods but also (in the next paragraph) I should declare an interface in the fragment and let activity implement it.
Now, the second way is used for callback methods like events, but I can also use getActivity().onSomeEventHappened(), can't I?
Could someone explain me the differences? Because I cannot see differences among them.
There is no difference in the end result if you know that getActivity() will always return the type of Activity you expect.
However using interfaces is a good practice because it decouples your Fragments from a particular implementation of an Activity. So later on in the future if you decide to use your fragments with a different activity, all you have to do is have that activity implement your fragments Interface to be alerted of any fragment events.
You should always strive to have decoupled components if you want an application that is easy to extend without side effects.
You can not always simply call getActivity().onSomeEventHappened(). Just imagine this case: You have two fragments, one with ListView and other which shows image based on listItem selected. In second fragment you cannot just call getActivity().onListItemClicked(), because your activity has no such method, but if activity implements interface and catches those event from the first fragment, then you are able to pass info about event to the second fragment and how the right image.
Related
I'm trying to access a function in one Fragment (f1) from another Fragment (f2). It seems that i have to make my function in f1 public and static to be able to access it from f2.
I've read that it's not a good idea to access one Fragment from another, so i've tried to make f2 access my Activity, which then connects to the function in f1. Although, even doing it this way, i still have to make my function in f1 public and static.
I don't reuse the Fragments, i simply have them in a ViewPager for swiping back and forth through the Fragments.
At the moment i have a lot of static variables because i have to make my functions static to access them from other Fragments.
Am i going about this the wrong way? Is there a better way?
Thanks in advance.
You're going down a road of much pain unless you are very controlled about what you do.
First of all, sharing state through static methods and variables is a fairly awful way of doing things, and static members won't be able to access anything in the instance of the fragment. If you really think you need to use static methods, don't bother putting them in the fragment classes. They don't provide an advantage there. Put them in a common class that they all reference.
Second of all, if you're using a ViewPager with fragments, you can't be guaranteed that any given fragment's view hierarchy even exists at any moment in time. This is because ViewPager typically only keeps fragment views alive that are on the current page or on +/- 1 offset from the visible page. So if you need to tell a fragment at offset +2 from the current fragment, you won't be able to make visible changes to it.
Instead, the easiest thing to do is create an object that maintains whatever state you want to share between the fragments, and have them all make changes to that one object. If you need instant changes to other fragments, you can use something like an event bus to have those changes communicated to other active fragments.
What you're trying to do is in general fairly complex. Expect to spend a lot of time designing a correct solution, and be sure to learn how fragments and ViewPager works very well.
You got two questions
1. Am i going about this the wrong way?
Yes, its not recommended to have the methods & variables declared static just to make them used to access from outside of your class.
2. Is there a better way?
Yes, declare the methods as public (but not static) inside its fragments.
From the activity (which is hosting the fragments) get the reference to the fragments using FragmentManager classes methods findFragmentById() or findFragmentByTag() then call the methods.
Sample :
Fragment fragment =
fragmentManager.findFragmentByTag.findFragmentById
(R.id.fragment);
or
Fragment currentFragment =
fragmentManager.findFragmentByTag("fragmentTag");
If you really require both of your functions to be isolated, you can use Broadcasts. Just send a Broadcast from one fragment and have the Broadcast receiver in the other fragment.
I have faced with the problem. My Activity is fragment container, so to communicate between activity and fragments I used common Callback approach. In this case my activity has to implement tons of callback interfaces depending on fragment count.
I don't like to hardcode and unreadable code. In my case my class declaration can take several lines to list all interfaces.
I am trying to get rid of this.
There is another approach is to use EventBus pattern.
In activity
EventBus.getDefault().register(this);
In fragment
EventBus.getDetault().post(new MyEvent(description));
And handle several event types in activity.
Maybe there will be better to use EventBus here instead default Callback approach ??
Or maybe there is my fault that my activity is holding a lot of fragments (God Object) and it is better to use activities instead Fragment ?
Please suggest which approach is better ?
For simple one Activity to one Fragment hierarchy, callback is simplest decision to go. But think about Activity containing a Fragment, and the Fragment contains swipe-able ViewPager, and each tab of ViewPager has Fragments A,B,C.
The Fragment A,B,C will go to long journey to send event to mother Activity, and it can be lost interface connectivity between Activity and children when they are restored during crazy complex Android Activity-Fragment lifecycle dances. In this case, eventbus like otto can be a good choice.
The drawback of event bus approach is, it is hard to maintain where the event is come from. So, keeping a few sender is recommended.
Your interface approach is awesome, just keep up with them, and maybe try and slice/make your interface static and add all the little little voids and return methods to that interface so you can just implement one and call the functions.
EventBus? how about LocalBroadcastReceiver ? its a matter of preference and which one you feel will suit you better, after all if you handle 10,000 request and hate having 100 interfaces, you will end up using 1 and nesting 99.
& just forgot, it is better to hold alot Fragment instead of Activity because at the end of the day the Activity lifecycle is pretty hard to maintain second of all you can not really control Activityies well all as compared to Fragments and Fragment is a good slave, serves you better
hope its valuable
Lets say I will be using several fragments(Action1Fragment, Action2Fragment etc.) within an activity(ActionActivity). I want to access some elements of activity object, or call some methods of ActionActivity. It is generally offered to create a event callback . What if I keep a reference to ActionActivity within Action1Fragment instead of keeping a reference to CallBackInterface which is actually implemented by ActionActivity since I will be using these fragments only within a particular activity.
I am kinda confused by the idea that Activity might be dead while reference of interface might still be alive(it sounds ridiculous when I read it again but it is OK if I managed to explain myself).
The Android Developer tutorials recommend that you use a callback interface on your fragments. The activity that hosts the fragment must implement the callback interface. The fragment does getActivity() and casts it to the callback interface, and then makes the callback.
This is the recommended way to promote a more modular design. It would not matter if your fragments will only ever work inside one activity. But if you want to make more generic fragments that could be used by different activities, then the above design pattern starts to become useful. (For example: a telephones fragment inside an person fragment and a company fragment.)
Suppose you do it the other way: the fragment does getActivity() and casts it to PersonActivity. The fragment then has access to all the public methods of PersonActivity. But this design pattern becomes much more ugly when you need the other activity to also use the fragment. The fragment would then have to be changed to first try and cast to PersonActivity, and if that throws, try the CompanyActivity.
The recommended design pattern basically gives you a way to make an activity compatible with the fragment instead of vice versa. The fragment only knows about the callback interface and not about any of the activities itself. The activities do know about the fragment because they implement the callback interface but they already knew about it because they constructed and initialized an instance of it.
Does that make sense?
I am new to Android Fragment and trying to learn Fragment to Activity communications.
What is the better approach(best practice) in Android for Fragment to Activity communication?
Lets say I have FragmentA and ActivityA.
After my screen popups FragmentA, I would like to perform somemethod(probably UI related) in ActivityA
Here are two(pattern) possible
Solutions:
In FragmentA getActivity and cast the Activity to ActivityA and then call somemethod.
In FragmentA create an interface callback and then implement that callback in ActivityA. Then on the callback, call somemethod.
Which pattern is more common/perfer in Android development and why. Or do you have an even better way to communicate from fragment to activity in Android to share with me?
Any comments, opinions, and suggestions is highly appreciated and welcome. ^^ .
The second solution is the preferred one, because it allows your fragment to be more independent of its hosting activity.
If in the future you decide to put your fragment on a different activity, there are no changes needed on the fragment, and you will only need to implement the interface on your activity.
I'll add a third solution which is using an event bus (Otto for instance), which also works, although some might argue that it makes your code a little less readable.
First method will be a bad practice. Second method will work fine but your fragment is going to be tightly coupled with your activity.
There is one more better approach is to use some event bus library like otto
Using this you can communicate effectively with loose coupling in your activity & fragment.
Your second approach is more flexible. You might not see a huge benefit in one activity and one fragment case. If you have to use the same fragment in another activity, it will most likely break by casting your activity like that. That said, there is nothing wrong with the first approach, but it is just a little restricted.
First pattern is best when your fragment is used only by one activity.
Second approach is needed if you want your fragment to communicate with some other objects not the activity that hosts fragment. If you always want to communicate with hosting activity callback is not needed. Just create an interface and implement it on as many activities as needed. Then in your fragment cast activity returned by getActivity().
MyInterface myInteface = (MyInterface) getActivity();
myinterface.somemethod();
You can even check if activity implements needed interface(s) etc.
The interface approach works fine and is more flexible in so far as it doesn't tie your fragment to the activity directly. One thing you should also consider is how much work the activity might need to do, that is it may end up managing several fragments. This has a tendency to lead to 'fat fragments' as my question here asked when I started using them
I already know how to make a fragment in Android. I want to open another activity in the same fragment on a button click event. The button is inside a fragment class.
How do I do that?
There are two possibilities depending on what you need:
Fragment Receive Result that demonstrates starting a new Activity from a Fragment, and receiving a result back from it.
setTargetFragment may be used, for example, if this fragment is being started by another, and when done wants to give a result back to the first. An example is available here
All Fragment-to-Fragment communication is done through the associated Activity. Two Fragments should never communicate directly.
Here are some tutorials with example
http://mobile.tutsplus.com/tutorials/android/android-sdk-using-fragments/
http://developer.android.com/training/basics/fragments/communicating.html
EDIT: April 2013
I like #AlexLockwood's comment.
In the case that one fragment starts another fragment, it's fine to just use setTargetFragment(Fragment, int) and communicate with it directly by calling getTargetFragment(). Communicating with Fragments through the activity is usually a good idea because it keeps your fragments loosely coupled from one another.