Android MVP : One Activity with Multiple Fragments - android

I have an Activity that hosts multiple fragments that define each step in a registration flow for a user. The flow is complex and the next step is defined by user actions in the previous steps.
The flow is like below:
MainActivity | Fragment1 --> Fragment2 --> Fragment3 --> Fragment4
\
--> Fragment5 --> Fragment6
Following MVP, I have View & Presenter for each Fragment involved. The concern I have is how to communicate between the Fragment and the Activity in an MVP way. The result of each Fragment needs to be available to the Activity to decide what Fragment needs to be shown next.
One of the approaches I have thought of is to have a listener defined for each fragment which is implemented by the Activity. I somehow find this a little ugly because in the end the Activity needs to implement 6 of these and doesn't look scalable.
What would be a better approach?

In my project I use the fact that each Fragment has access to the parent Activity. My solution is:

As you have mentioned that you want to communicate with fragments using MVP.According to me I found 2 solutions.
Solution 1:
Callbacks using interfaces, rather creating one interface & bombarding lot of methods that need to be perform on activity/fragment. Try to create more than one interfaces & add methods according to your functionality & implement those according to your use.
Solution 2:
Event Buses is the other solution using MVP, where your view observes the bus & picks up event. Following points to take care when dealing with event buses:
a. If you are using publishing or subscribers within an Activity of Fragment they should be registered and unregistered with their lifecycle. Otherwise, it's likely you will encounter memory leaks or dangling references that can cause your app to crash.
b. Be wary about publishing events between Fragments. Events cannot be published or received when a Fragment is not running. If you have a Fragment publishing a message to another Fragment that isn't currently executing and then swap one for the other, it's likely the event will not be processed correctly. The EventBus library has a way to replay this event, but the Otto framework does not.
For Event Buses you can refer two libraries:
- GreenBot : https://github.com/greenrobot/EventBus
- Otto : http://www.vogella.com/tutorials/JavaLibrary-EventBusOtto/article.html
Conclusion
If you are dealing with small operations on Activity/Fragments then dealing with interfaces is better option. Event Buses increases your app performance, also dependencies for larger scopes you can go for event buses.

Related

How to update two identical fragments in Android

I am working with Fragments in Android. I have two identical fragments FragA and FragB. Since they are identical: I need a method that says if I am on FragA and a textView in FragA changed or updates the same textView should change/update in FragB. Can anyone help me with creating a method that takes data from FragA changed about a particular View and passes it to FragB to update its View.
I have tried using interfaces and ViewModel for communicating with fragments, but I can't seem to figure out how to update two identical fragments when let's say one of them changes.
This is actually an easily approachable problem these days. With a ViewModel we can achieve this easily.
We can make a ViewModel where our MutableLiveData can live.
Our two (or more) fragments can observe the LiveData events and both update at the same time.
I could post some code but I really think this CodeLabs is exactly what you are looking for and can get you up to speed in just a few minutes.
Android Lifecycle Aware Components Codelab
You can easily do this with an external and awesome library, https://github.com/greenrobot/EventBus . This is a hidden gem for easy fragment to fragment communication in android. The docs are pretty self explanatory.
Please note: if you are using eventbus please remember to register eventbus only in the fragments OR classes you will be using it in, you do not have register an eventbus even in the class from where you are posting the event, else it will be giving you a compile time error. Also DO Not forget to unregister the eventbus using EventBus.getDefault().unRegister(this); or EventBus.getDefault().unregister(context);
in order to prevent memory leaks

Inter-fragment communication

The Android Developer Documentation states that one should avoid direct communication between fragments by implementing an interface. On further searching, the reason that I found for this is that it causes tight-coupling between the fragments. I'm having some difficulty understanding why it causes tight coupling and why that might be a problem.
Could someone show, by example code:
How direct communication between fragments would work.
Why this approach would be problematic
How using interfaces would solve the aforementioned problem.
Android fragments are often thought of as Views in MVP or MVC patterns, they should not contain any application logic within. All meaningful events from the fragment should be delegated to presenters which are often implemented via Activity.
Suppose you have a fragment A and a fragment B. Fragment A displays a list of items and fragment B displays details for the selected item. If you communicated fragments directly it would create a tight coupling between them since fragment A would need a concrete fragment B reference in order to instantiate it. If your application requirements change, for instance by showing fragment C instead of B, the tight coupling will pop out and you would have to deal with it. You can avoid this coupling by introducing a Presenter or Controller interface into your fragment. By calling this interface methods you can be sure that the implementation of your presenter logic is decoupled from fragment appearance logic.
For more information about developing decoupled application architecture check out this article http://fernandocejas.com/2014/09/03/architecting-android-the-clean-way/

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.

Fragment Callbacks vs EventBus in Android

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

Android activity/fragment responsibilities for data loading

When starting a new application for a client, I am asking myself again the same question about who should be responsible for loading data: activities or fragments. I have taken both options for various apps and I was wondering which pattern is best according to you in terms of:
limiting the code complexity.
handling edge cases (like screen rotation, screen going power save, loss of connectivity, etc.)
Option 1 - Activity loads data & fragment only displays it
This allows to have fragments that are just fed a bunch of objects to display. They know nothing about loading data and how we load that.
On the other side, the activity loads data using whichever method is required (for instance initially the latest 50 entries and on a search, loads the search result). It then passes it to the fragment which displays it. Method to load the data could be anything (from service, from DB, ... fragments only know about POJOs)
It's kind of a MVC architecture where the activity is the controller and fragments are the view.
Option 2 - Activity arranges fragments & fragments are responsible to fetch the data
In this pattern, fragments are autonomous pieces of application. They know how to load the data they are displaying and how to show it to the user.
Activities are simply a way to arrange fragments on screen and to coordinate transitions between application activities.
In theory you can do whatever you want, if it works.
Actually, the fragments and activities display data and deal with their own life cycles.
Since fragments belongs to activity so you have to use both in conjunction to better handle all the data but mostly it depends on your needs.
If you keep in mind the idea that the Fragment should provide the UI and the Activity should provide the processing then you have a good division of concerns and code which should allow the Fragment or the Activity to be reused.
If you know about the MVC - Model View Controller - design pattern then you can think of the Fragment as the View and the Activity as the Model.
Things get much more interesting when you build an application with multiple Fragments.
Some key points as a decide factor -
The idea of a Fragment is that it is a wrapped up chunk of UI that
can be used by any Activity that needs it. On this basis you have to
ask yourself if the event that has to be handled is the same for
every Activity or unique to each Activity. If it is the same then the
event handler is better written within the Fragment.
The Fragment doesn't have a UI of its own - it is displayed by an
Activity that the Fragment is associated with. The events are
generated by objects in the View hierarchy, which is owned by the
Activity. If you try to use Android Studio to add an event handler,
for example, it will add it to the Activity and not to the Fragment.
You can define the EventListener that you want to handle the event
in the Fragment and then hook it up to the View object in the
Activity in which you want to generate the event.
A Fragment is a class that implements the onCreateView method to
supply a View hierarchy that can be displayed by an Activity.
To use a Fragment in an Activity you have to add it using a
FragmentManager and a FragmentTransaction. You can add the Fragment
using the add method but nothing happens until you call the commit
method.
After the method that used the commit, usually the Activity's
onCreate, terminates the CreateView event runs the Fragment's
onCreateView and the Fragments View hierarchy is added to the
Activity's content.
You have to write code to save and restore any additional state the
Fragment may have.
If a task is common to all instances of the Fragment then its code
should live in the Fragment.
In particular the code to handle events can be defined within the
Fragment.
The Activity should be used to host code that processes the data
provided by the UI.
Attaching Activity event handlers to the Fragment's UI or is
difficult to do correctly.
From scenarios make decision what your app will be. Is it service,
activity, widget , even a content provider or a complex system,
including some different components. Test your decision against
scenarios.
All of these have to work after the Fragment has been destroyed and
recreated.
(1) Initialization of the Fragment, (2) Saving and restoring the Fragment's
state and (3) Implementing something like an event mechanism so the Fragment
can get the Activity's attention
The hardest part is implementing something like an event mechanism.
In the case of the complex system, distribute functionalities and
data entities among application components. Make a list of components
and what they are (activities or smth else).
Make the list of UI components with description what they do (not HOW
yet) These will be widgets and activities or fragments or layouts
later.
Often you will want one Fragment to communicate with another, for example
to change the content based on a user event. All Fragment-to-Fragment
communication is done through the associated Activity. Two Fragments
should never communicate directly.
When your app is perfectly modular, fragments don't know about each
other. You can add a fragment, remove a fragment, replace a fragment,
and they should all work fine, because they are all independent, and
the activity has full control over the configuration.
You can't do anything with a Fragment unless you start a transaction.
Within the transaction you can set up what you want to happen,
usually add the Fragment to the current layout, but nothing happens
until you use the commit method.
Efficient handling of data with Screen Orientation -
When screen orientation changes, Android restarts the running Activity (onDestroy() is called, followed by onCreate()).
To properly handle a restart, it is important that your activity restores its previous state through the normal Activity lifecycle, in which Android calls onSaveInstanceState() before it destroys your activity so that you can save data about the application state. You can then restore the state during onCreate() or onRestoreInstanceState().
However, you might encounter a situation in which restarting your application and restoring significant amounts of data can be costly and create a poor user experience. In such a situation, you have two other options:
1) Retain an object during a configuration change
Allow your activity to restart when a configuration changes, but carry a stateful Object to the new instance of your activity.
2) Handle the configuration change yourself
Prevent the system from restarting your activity during certain configuration changes, but receive a callback when the configurations do change, so that you can manually update your activity as necessary.
What I would do is manage all data flow (bluetooth, database storage, etc)
in the Activity and use Fragments only for UI display or handling user input.
This way is easier to handle configuration changes/ screen rotations.
Also, if data flow things are heavy to be on UI thread, consider using a Service with a background thread.
If it is a "one shot" thing, you can use an IntentService,
otherwise you can implement a Bind Service and request a bind from anywhere you have Context.
For more read - fragment-and-activity-working-together.
Ideally neither Activity nor Fragment with UI should contain any "model" logic - these classes should be lightweight and responsible only for UI logic. But when you decide to make a separate model object you have a dilemma to choose where to initialise and store this object and how to deal with configuration changes. And here comes some handy trick:
You can create a model Fragment without UI, make it retain instance to deal with configuration changes (it's AFAIK the simplest way to save data across config. changes without troubles) and retrieve it anywhere you need via findFragmentById(). You make all expensive operations inside it once (using background thread, of course), store your data and you're done.
For more info, see Adding a fragment without a UI section.
UPD: There's now a better way to deal with configuration changes: ViewModel from Google's Architecture Components. Here's a good example.
I prefer and always implemented Option-2 over Option-1.
Reasons for not selecting Option-1:
We should have listeners for events triggered in Fragments and pass it back to activity to load data, process it and push it back to fragment, which makes work more complex.
An Activty can load any number of Fragments, Typically you end up questioning these questions to yourself in a scenario where your app is highly scalable and is already huge. Writing all the events in an activity and passing it over to fragment will be an complex altogether.
As #Ved Prakash mentioned, Handling screen orientation becomes complex if orientation is handled by Activty.
I have an example:
your application have 2 features A and B. the 2 features are independent each other. and each feature has a lot of screen.
you should create 2 activities A and B because when Activity A is used, Activity B should be released to reduce memory of app. And the same when B is used, A should be released. The memory of Context A and B are independent, if you want to send data from Activity A to B you must use intent or use global variable in Application Context. intent is managed by OS, not by application. When A send intent to B, if A is destroy is no problem with intent send to B. Activity is App module, it is can call by other applications (fragment is impossible).
for example: feature A has a lot of screen (ex: Fragment1, Fragment2). they use the same data and depend on each other. each screen should be a fragment. and when process with data you can get reference to data by calling function getActivity() and then get reference to variable of Activity context (or Activity memory) to write or read it. Fragment1 and Fragment2 are belong to Activity A Context.it means that Fragment 1 and Fragment 2 can transfer data with each other via variable of Activity context, it is easy to do . noticed that Intent is managed by OS,it is so expensive when send data via Intent.

Categories

Resources