I have a dashboard that is a fragment. Everytime I click a button, the dashboard is replaced by another fragment.
The click listener is implemented inside the dashboard fragment class. But I read somewhere that the better way to do it is to make the listeners inside the activity. Is it true? Why?
If yes, I can change it, i only have to copy the method in dashboard fragment to the activity, and make use of XML onClick feature.
I honestly can't think of a reason for declaring an onClick listener for a fragment in the activity.
First, fragments are suppose to be modular. Maybe you use it with this activity or that one. Putting the onClicks in the activity hardcodes a relationship between the two. Your activity is searching for the fragment, which isn't always there, and your fragment can't work except in that activity.
Second, where you declare your on click determines where it's implicit reference will be to. If you declare it in the activity, it can call activity functions, but It has no idea which fragment it came from. How does it reference fragment functions / data? Sure there's elaborate workarounds but why?
On the other hand, if you put it in the fragment, it can call the fragment functions. and it has the same life-cycle as the fragment (being attached to a fragment view), so the implicit reference isn't going to create a memory leak (by itself anyways). And if you want to call the activity, just use getActivity and cast it to your interface or subclass.
Related
In my fragment I have a 'dismiss' button that should behave in a different way dependent on which Activity called its parent activity (say TutorialActivity).
In the TutorialActivity I am already determining which Activity called it. How to pass that data down to the fragment?
My fragments reside in a PagerAdapter and I wouldn't like to need to pass this info as a 'newInstance()' parameter every time, as it seems an overkill, taking into consideration that this parameter would be the same for each fragment in my FragmentStatePagerAdapter.
You can access the variable from Tutorial Activity by making this variable public. Suppose variable name is parent. You can access it by using instance of TutorailActivity (suppose instance of Activity used in fragment is mTutorialActivity) then it should be like mTutorialActivity.parent.
But you need to pass instance of TutorialActivity as it may be used for other purposes also like fetching strings from strings.xml and other purpose. So it would be beneficial to pass Activity instance instead of variable.
What I ended up doing: I implemented said "different behavior" in the TutorialActivity itself, having moved the dismiss button up from the fragment. Then a simple onClickListener and a switch statement inside of it.
i am trying to alter the activity content from fragment. for that i want to pass the activity handle inside fragment and do the required changes.
If i can do that why there is more difficult way of interface etc.
You can call getActivity() from the Fragment.
If you want to get your activity specifically you can cast it
((MyActivity) getActivity()).someMethod()
This will tightly couple your Fragment to your activity and prevent you using the fragment in a different activity easily so be careful.
Also you need to be careful with lifecycles and such as a fragment can become detached from an activity causing a NullPointerException from time to time. So it is recommended to wrap this in a null check
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 have one Activity which handles 5 fragments. Every time the activity replaces each fragment onCreate and onCreateView are being called. In order to avoid this i created a HashMap where i store each fragment. Before the activity replaces a fragment it checks the hashmap if this fragment already exists. If it exists it replaces the old fragment with the instance from the map. In other case it instatiates the fragment and after that it replaces the old own.
Despite i avoid the instation of the fragment when i find it on hashmap, the onCreate and onCreateView are being called. How can i avoid this? Is there any other way to achieve my goal?
First of all there is no use for a HashMap to save the references of your Fragments. You can set a tag to a Fragment at the point you add/replace it. Have a look at the FragmentTransaction.add(int, Fragment, String) and FragmenTransaction.replace(int, Fragment, String) methods. If you provide a unique String for the tag you can retrieve the Fragment with the FragmentManager.findFragmentByTag(String) method. A container for Fragment references is redundant.
To the point:
If you use the replace/add method to show a Fragment the onCreate() and onCreateView() is called. To avoid the onCreate() call you can just attach and detach your Fragments. This way only onCreateView() will be invoked. But it's not possible to prevent the onCreateView() call.
Maybe update your question with some details what you want to achieve, because it sounds you are completely on the wrong track.
Your goal is not very cleared.
When you deal with fragment, keep in mind that your control over their life cycle is limited, you only extend (system controlled) object. You can read on the life cycle of the fragment here: Creating a Fragment.
Assuming your goal is to switch between 5 active fragments, I can think of two options:
option 1: design your fragment so they can be recreated quickly, maintain the data in some other place, and provide it to the fragment, which only do the work of display the data.
option 2: The android support library has two fragment adapters, FragmentPagerAdapter, and FragmentStatePagerAdapter. The first is an adapter which keep the fragments in memory.
How can i avoid this? Is there any other way to achieve my goal?
If you really want to avoid your activity instance to be recreated again and again just use android:launchMode="singleTop".
Example:
<activity
android:name=".YourActivity"
android:label="SomeLabel"
android:launchMode="singleTop">
</activity>
From developer docs,
If an instance of the activity already exists at the top of the target
task, the system routes the intent to that instance through a call to
its onNewIntent() method, rather than creating a new instance of the
activity.
Source: http://developer.android.com/guide/topics/manifest/activity-element.html
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.