I've an activity with a FragmentStatePagerAdapter that contains two fragments of the same class (practically an activity with two tabs).
At runtime, I need to update both fragments layout with fresh data, after user input.
In particular a user click on a fragment, and the other one is updated consequently.
Any simple method to do that?
Fearing angry backlash because I'm doing ugly things and am now telling about them:
Let your Fragment register itself in the Activity so when you need to reload you can just call the fragment reload function directly.
Probably less ugly:
Let the activity broadcast reload, and have your fragments register a broadcast receiver so they'll know when to reload.
Related
I am following MVP approach, and I have an activity containing 4 fragments. On App launch activity makes network call, and passes data to fragments.
In one of fragment i have recycler view, and it has Swipe to Refresh.
When user swipe to refresh i need to make network call from fragment, which i learnt is not a good idea, and also i am following MVP approach, so activity has the list of methods to execute in presenter, and presenter decided whether to grab data from local repository or remote.
So what should i do to perform swipe to refresh operation from a fragment.
Should i call activity method, and perform network call from there, and re pass the updated data to fragment, or is it fine to make a network call from fragment.
The answer is neither the Activity nor the fragment. The fragments and activities shall never "fetch" or "handle" data. Only display data. And deal with activity lifecycle with regards to this.
If you want to know further this will be a good read for you.
I have the following design:
MainActivity
| /->AddingActivity
|-------Fragment One---\->DialogFragment
|-------Fragment Two
|-------Fragment Three
|-------Fragment Four
MainActivity hold the fragments. Fragment One can start AddingActivity (with context from MainActivity) which adding data to DB and then all fragments should refresh with the new data. DialogFrgment started from FragmentOne is adding some data to SharedPreference and only the FragmentOne should know about this. MainActivity impliments DialogFragment.OnTimeSetListener (The dialog picks time) and then in MainActivity onTimeSet triggers function in Fragment One to refresh the data.
What I did for now is overridden OnCreate in each fragment and the fragment refreshes when it returns back to view. But the app is bit laggy because each fragment refreshes its neighbors and I get some fragment refreshed twice.
Can you please advise me about the correct approach to this design, and how can I make the app work more smooth and correct.
Your approach of MainActivity implementing DialogFragment.OnTimeSetListener and then notifying FragmentOne seems kind of strange.
This is how I would do it:
FragmentOne and MainActivity implement DialogFragment.OnTimeSetListener as well. However, only FragmentOne should be notified from the dialog fragment when the time changes, as it is the one responsible for setting the time. Then when this happens, FragmentOne should notify the activity:
#Override
public void onTimeSet(Time time) {
((DialogFragment.OnTimeSetListener) getActivity().onTimeSet(time);
}
When MainActivity receives the time set event, it must update the other fragments, but if possible, it should not re-create them. Just let them know the time was set so that they can update their views accordingly. Each fragment will update itself depending on what it is displaying, etc.
In case the problem persists and you still have lag, check if you do too much work on the main thread, e.g. a long-running for-loop and try to execute it on another thread.
Maybe you can use LocalBroadcastManager to refresh the the fragments , that way you can have the control to which fragment to refresh and not all at the same time , and you should also check if the DB is causing the lag.
Here is an example how to use LocalBroadcastManager you should implement it on your own way.
https://android--code.blogspot.com/2015/12/android-how-to-send-and-receive-local.html
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.
First, I'd to state that I've been searching for a solution for this problem for three days now, that may means either I'm not asking the right question or not using a good approach. If any, please guide me in the right direction.
This is the scenario: I've an Activity and a bound Service. The Service holds some data and processes it as necessary while posting a persistent (ongoing) notification with some information. The Activity has three Fragments inside a ViewPager that displays the data processed by the Service.
The Fragments are a List Fragment, that shows the active data entries available, a Details Fragment that displays the details for each data and a Parameters Fragment where the user can modify how the data is processed.
[Service] <-> ([Activity] -> [ViewPager([List], [Details], [Parameters])])
Everything works just fine. My Activity binds to the Service, the ViewPager is created after and then the Fragments fetch information trough an Interface.
Here comes the fun part... Screen Rotation!
As the Service binds asynchronously, when the user rotates the screen the Fragments no longer have the data because the Activity is bounding the service while they're already present and not recreated thanks to the ViewPager.
I've been trying to figure this out but it seems that I don't have the knowledge to solve it. I've tried making static references to the fragments, setting them up before the service is rebound but I can't get a stable solution.
I'd be using android:configChanges in my manifest but there are different layouts for each orientation.
Again, if I'm using a bad approach, please, guide me!
Difficult to suggest when I don't know your code but thinking out loud....
Can you have a "worker fragment" that is never displayed (i.e headless) and has setRetainInstance(true) set so it does not lose any state you have set.
Your worker fragment would bind to the service instead of the activity and maintain a reference to it.
If you need to communicate with your Activity, you can do this with callbacks.
Your other fragments could communicate with the worker instead of the Activity.
This process would basically make the activity little more than a shell into which the rest of your components are hosted. Rotation would lose nothing because all data is held in the retained fragment.
During the screen rotation process the activity is completely destroyed and use of android:congfigChange is discouraged. but what you can do is you can override saveInstanceState(bundle) method in which you can save the data present in your activity at the time it is destroyed by the system in response to the screen rotation. and later receive it as the system passes the bundle to the activities onCreate(bundle) method or get it from the restoreInstanceState(Bundle) method.
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.