Always use fragment - android

In Big Nerd Ranch's Android Programming, it advocates AUF (always use fragment). Specifically, it has this to say:
"...adding fragments later can be a minefield. Changing an activity to
an activity hosting a UI fragment is not difficult, but there are
swarms of annoying gotchas. Keeping some interfaces managed by
activities and having others managed by fragments only makes things
worse because you have to keep track of this meaningless distinction.
It is far easier to write your code using fragments from the beginning
and not worry about the pain and annoyance of reworking it later, or
having to remember which style of controller you are using in each
part of your application."
The book doesn't expound on what the annoying gotchas are. What are the gotchas?

Biggest of all is Context. as Activity is driven by Context (not directly). when you need context in an activity you have it there all the time. same is not with the case with fragment, in fragments you can call getActivity method to get parent activity but when porting code from Activity to fragment you have to deal with supplying it everywhere.
Another problem could be life cycle of Activity. where activity lifecycle is simple and functions like onResume, onPause are pleasure to use same can not be said for fragments. Adapting things which were designed for Activity life cycle into fragment life cycle can be nightmare.
Having said that, if things are not complex and you need to handle only one task it is safe to go with activity to begin with.

Because you are at the very start of decision making, I want to leave this here:
https://corner.squareup.com/2014/10/advocating-against-android-fragments.html
On the bottom line, this blog says that the lifecycle of a fragment is too complicated and therefore it advocates against using fragments, in favor of an Model-View-Presenter-Pattern
A personal note: the wordy comment from CommonsWare hits the spot. I blindly used fragments because they were there and I never questioned them. But after reading the above article, I've changed my mind.

Related

Fragment callbacks explosion, how to deal?

I am creating my app with using fragments. I have something like main activity, it has FrameLayout as root layout to hold fragments.
After much thought I have decided to separate my application logic in several parts, for example : MainActivity is responsible for app basic navigation (MainPageFragment, CategoryListFragment, ProductListFragment, ProductDescriptionFragment), AuthActivity is responsible for autherization, registration (SignInFragment, RegistrationFragment, RecoverPasswordFragment).
A little about my app. If you have recommendation or don't agree with app structure, I would be grateful for any critics.
What is the problem, as you can see my MainActivity has many responsibilities. There are four Fragments now but it can be more in the future.
Lets consider next situation. In my MainActivity I have MainPageFragment and this fragment in turn of course has some views. And on click event I need to change fragment, for instance from MainPageFragment to the CategoryListFragment. In this case I have several ways to handle clicks or other events from framgents.
The most common way is to have activity implements callback interface defined in fragment class as nested class inteface. This approach is quite good and easy to use. But what if my host activity has to handle multiple callbacks from fragments, to say more, there can be more than one callback from single fragment, class(activity) declaration starts growing, class body too. What are another possible approaches to solve this problem.
You can handle all clicks, events directly inside fragment (start activity, replace framgent......) you can do this painless, but for me personally callback approach looks better, but maybe there is nothing bad, and I can use this approach.
Use one or several interfaces for getting information from fragments. For example create class CallbackEvent for holding such info as framgentId, eventType .... Using this approach we can reduce interfaces and methods, but Activity class body can become larger in first approach.
Use something like EventBus pattern to communicate between app components via third party service.
Of course there are some other ways to do this, but I have described most popular.
Please suggest, or just explain how to do you solve this problem in your apps, what approach is better, how to built this communication easy to maintain.
I am grateful for any advice,critics in advance.
If your app becomes more complex using the callback pattern will get messy, especially if fragments need to communicate with fragments. I'd only use that pattern for apps with low complexity (activity, one or two fragments).
Clicks, events etc. should be handled inside a fragment if whatever happens stays within the fragment. Don't replace a fragment from within the fragment, that's the Activity's responsibility. It might look easier to just do a getActivity().someMethod in the fragment but this leads to hard to maintain code. You might understand now what it's doing but will struggle in half a year.
This approach looks messy to me too (similar to 1.)
That's the one I'd recommend. I'm using EventBus (https://github.com/greenrobot/EventBus) but there are alternative implementations like Otto (https://github.com/square/otto) and I've never looked back to the times when I used the callback pattern. Using an EventBus decouples the communication between the different components and your code becomes much simpler and leaner. However you need to be careful with that approach since there are some pitfalls. One is that it gets much easier to communicate from any component to any other component which could lead to even messier code than the listener/observer pattern. Another one is that events are asynchronous compared to synchronous listener calls so you need to make sure you're only receiving the "right" events at the right moment in the component's lifecycle. The main advantages of an EventBus approach are IMO:
A message is always an object forcing the developer to code object oriented compared to the more functional listener method calls
It decouples the different components. Publisher and subscribers don't have to know about each other. Decoupling the components will make your code much leaner and easier to read (and maintain).
It can be used by arbitrary components. E.g. I replaced all LocalBroadcastManager calls by EventBus messages (EventBus is MUCH faster that using a LocalBroadcastManager). Being able to communicate between arbitrary components is especially convenient if the components can't access each other directly (like a Dialog and a Preference object)
I have two rules of Fragment - Activity separation.
One is logic. Anything that deals with View (layout expansion, display, listeners, etc) should go inside a Fragment. Important background processes (http requests, file reading, image processing, etc) should go inside Activity. Part of the reason is explained in my second point:
Lifecycle. Activity's lifecycle outlasts Fragment's. Fragment is also fragile it doesn't even retain its views. And this is the reason Fragment should be decoupled from Activity. Listeners and callbacks are tight coupling and they are the cause of countless null pointer exceptions when some process tries to update a View of a Fragment that has called its onDestroyView. Having said this I'd suggest Publisher - Subscriber pattern like Event Bus where you can plan a message delivery in which it gets digested only when a publisher (which in this case corresponds to Fragment's view) is available.
The numerous click listeners you have are related to how you design your UI. Moving code around doesn't really help much, unless you trim down your layouts.

Android best practices for Fragment to Activity communications

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

Should we be using setTargetFragment()? I thought Fragments should not be communicating with each other

The android developer tutorials recommend me using the host activities of fragments to pass around data and whatnot, so why is there a set/get target fragment method?
My application thus far contains a host activity, and a fragment, which has a button that launches a DialogFragment, in which there is a button that launches ANOTHER DialogFragment. Using setTargetFragment/getTargetFragment has made this whole ordeal somewhat confusing though, so I am thinking of reimplementing to let my main activity handle DialogFragment.show methods through my main fragment's custom interface.
Is this the right way of thinking? Or is there no harm in using setTargetFragment? Can anyone provide good and bad examples of using it?
Also, you may end up with exception of no target fragment found in fragment manager. This happens if after rotation (or other config change) your target fragment will not be readded to the fragment manager by the time when caller fragment will be adding.
Imagine you have some sort of Confirmation fragment which you add from MainFragment as so:
ConfirmationFragment frag = new ConfirmationFragment();
frag.setTargetFragment(this, 0);
getFragmentManager().beginFragmentTransaction().add(R.id.container, frag).commit();
Now on some confirmation button click you invoke a method from MainFragment by calling:
((MainFragment)this.getTargetFragment()).onUserSelectedGoodButton();
This is pretty and simple, but if you will rotate the screen and for some reason ConfirmationFragment will be added to FragmentManager before MainFragment, exception will be thrown, stating that target fragment is not found in the fragment manager
I don't think there is implicit harm in using setTargetFragment, however, I would only use it in very specific circumstances. For example, if the target fragment is only going to ever be used by the fragment (taking into account object reuse and designing your classes to be reusable when possible) and even then, sparingly.
By using them too much, you will end up with what you're seeing - confusing code that is hard to follow and maintain. On the outset, by marshaling everything through your activity you maintain a "flat" hierarchy that is simple to follow and maintain.
I think the decision to use setTargetFragment or not is a coding-style/philosophical one that, with wisdom and experience, it "feels" right or wrong. Maybe on your case, by evidence that you are questioning your older code, you are gaining that wisdom :)

Activity or Fragment in Android?

I have been researching this for about an hour and cannot figure out whether to use fragments within an activity or start a new fragment activity.
Some sites make it sound as if you should have 1 activity and EVERYTHING else is a fragment. Is that the more proper way now? I can't figure out when you use an Activity (or fragment activity) and when you use a fragment.
I have an app for a conference with:
-Speakers (and sub views/activities/fragments) for each speaker.
-Schedule (different sections for each day)
-General info
-Sessions (different sections for each session).
So do I have 4 activities each with their own fragments or do I just use 1 activity with fragments and nested fragments?
You could do it either way, but generally it is best to use an Activity (or FragmentActivity) for each "screen".
If the user sees your app as logically a single screen that has little panels appearing/disappearing for different kinds of data, then use one activity with a lot of fragments. If the user sees it as "going to different screens", then you probably want multiple activities.
If you go with the one-activity-many-fragments model, you may find that your activity's code gets really complicated dealing with all the possible configurations of fragments. That is a good sign that you may want to split it into multiple Activities. Similarly, if you go with the many-activities model, but find that things get complicated as you pass shared data between activities, consider merging the activities.
Converting from Activity to FragmentActivity is as simple as changing the extends and nothing else needs changing.
My conclusions:
I stopped using Activity and only use FragmentActivity as it is more flexible and more up to date and backwards compatible (Using the support library).
If the FragmentActivity has a component that is large enough to be a standalone component, or needs to be one, then I make it as Fragment.
I haven't come across something that would require a complete separate activity to be within another activity, but that should only be used if that component is large enough and completely standalone enough to need an activity for itself.
I don't fully understand your app to be able to make a specific call on which you should use, if you want my opinion, can you provide more details on what you are working on and how are those components connected.
Regards
Another consideration in choosing a more decomposed architecture (many Activities) might be the cost of destruction / creation in the Activity Lifecycle. Do you plan to use Explicit/Implicit intents to leverage existing apps? More death. So, you might have only one activity in a dispatch oriented model and clearly see your apps logic in one place, but how much state will you have to save/restore? Are there performance penalties for re-inflating or populating data resources?

Wrap Activity in a fragment, or an alternative solution

I have a kinda big, already published railway schedule app published on Google Play, and now I am planning to integrate bus schedules as well. My question is something like this:
At the moment, whenever the app starts, it loads the Activity, where you can search for train, lets call it A
I have already implemented a beta version of the bus search Activity, lets call it B
Eventually, I will come up with a hybrid solution, that will be able to search for trains AND buses at the same time, of course with some restrictions, lets call it C
Now, I want to implement the main screen so it will have swipeable tabs, and the tabs would be A, B, and C. I never really worked with theese kind of tabs, so my knowledge is not that deep, however, I came up with a solution, that would indeed work, but it is going to need a lot of recoding(keep in mind, my app was published more then a year ago), since I never really prepared for fragments. I am doing pretty much THIS thingie, and it works really great. However, this means that the main screen should be a FragmentActivity, which is fine, I can deal with that. But I just cannot supply A, B, and C Activity, as tabs, it will accept only fragments.
The question is: can I supplement my already coded Activity as a fragment, so I can swipe between them? Is there any wrapping mechanic I am not aware of? Any other solution, which you can show me? Just point me in the direction, I will do the rest. Or, am I f**ked, and have to recode everything from scratch? No problem, if that's the case, tho I would happily avoid it.
Thanks in advance, cheers. :)
What you can do is to wrap your fragment in an Activity. This would be the better choice if you've got multiple classes enclosed in your Activity. Otherwise, I would just go with wangyif2's suggestion instead.
In any case, should you want to do the former:
public class SampleActivity extends Activity {
...
public static class SampleFragment extends Fragment {
...
}
}
And when you finally initialize all this in an ActionBar
final ActionBar bar = getActionBar();
bar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
bar.addTab(bar.newTab()
.setText("Sample")
.setTabListener(new TabListener<SampleActivity.SampleFragment>(
this, "sample", SampleActivity.SampleFragment)));
I suggest checking out the API Demo from API 14+ samples. There's a really good example of this in FragmentTabs (com.example.android.apis.app.FragmentTabs).
Thank you both for the suggestions, I did try the method wangyif2 suggested, it generates way too much overhead in the code, since I did some kinda specific things.
I am going to check out some demos, but I guess I will recode everything from scratch, that seems to be the most clean solution at this point.
Instead of your original Activity A, B, C extending SherlockActivity, simply change them to extend SherlockFragments, and supply them to the Tabs.
Obviously there will be some compilation errors that you have to fix, namely the difference between activity lifecycle and fragment lifecycle, but once you fix them, you should be good to go.

Categories

Resources