I have an activity with fragment A. Fragment A hosts a list in recyclerview which requires an adapter. When an item from the list is clicked I want to open another fragment, say B, showing additional details about the item.
I can open fragment B in three ways:
From the recyclerview adapter itself where I will have the item position etc.
From fragment A using callback from the adapter, since the adapter has all the required info like position, object etc.
From the activity, again using callback. If i do from the activity, i will have to add callback interface from adapter to fragment A, and finally to the activity. Looks too much.
I want to know what is the best way to open fragment B.
Hey its not good practice to start the fragment from adaptor. because it will be very complex to find the container of fragment. so please always try to start the fragment from main activity which will be parent of all fragment.I hope its help you.
Option 2 is always good approach->
2. From fragment, A using callback from the adapter, since the adapter has all the required info like position, object etc.
"According to MVC pattern adapter is always used for binding view with lists. So adapter should always independent from the fragment so the Single Responsibility Principle will always be handled. So, there should be no dependency from the adapter to fragment but fragment to the adapter. When you call fragment or activity from adapter it will create a cyclic dependency with one another so memory will not clear until you finish the apps. You can call any callback method of the fragment from the adapter which method will call the desired fragment you want."
Related
I would like to change dynamically my List of Fragment which will be sent to an adapter in Parent Activity.
I have tried to send it by a Bundle but the RecyclerView is not refreshed.
I also have tried to implement a method in my Fragment to be called from my Activity.
What's the best way the do that?
Search for observer pattern
https://www.baeldung.com/java-observer-pattern
The idea is making your fragment like an observer for any updates
When viewpager displays one fragment, it will automatically load the fragment pages around it for performance reasons.
In my fragments, i have recycleviews with a popup menu to delete one item in the list.
I am facing a problem of deleting one item from one fragment, but that item still exists in the other preloaded fragments after I scroll to them.
It works only if I force the viewpager to reload the contents of its fragments by manually scrolling back and forth the fragments.
Is there a way to force reload the preloaded fragments by viewpager?
Your problem can be solved by using Interface. Google suggest using callbacks\listeners that are managed by your main Activity for communicating between fragments.You can use Interface which tells the other fragment to refresh its listview when you delete an item in current fragment.
For an overview http://developer.android.com/training/basics/fragments/communicating.html
Also a good question about this How to pass data between fragments
First create an interface to detect changes in your RecyclerView:
public interface MyRecyclerViewChangeListener(){
void onRecyclerViewDataChanged(int id);
}
Create a static variable in your Fragment or Activity which contains your viewpager:
public static List<MyRecyclerViewChangeListener> mListeners = new ArrayList();
Implement your interface to your ViewPagerFragments and do what you want in method you implemented.
In your fragment's onResume register your listener to mListeners like blow to detect changes:
MyFragmentOrActivity.mListeners.add(this);
And in your fragment's onPause unregister your listener:
MyFragmentOrActivity.mListeners.remove(this);
Finally notify your listeners when your recyclerview data changed:
for(MyRecyclerViewChangeListener listener : mListeners){
listener.onRecyclerViewDataChanged(id);
}
Edit : If you are changing your recyclerview's data after an async task result such as a web api call, you can register your listener in fragment's onCreateView method and un register in onDestroyView method. So you can catch changes in your fragments.
I am not sure if i'm getting your question right but i think this should do it.
YourViewpager.setOffscreenPageLimit(0);
Now the fragment should be destroyed if it is not active and will be recreated if you open it again.So the data change should be recognized.
Hope I could help
Try setting mViewPager.setOffscreenPageLimit(1) such that it will not pre-cache any fragment or you could use FragmentStatePagerAdapter inside viewPager to achieve what you want.
Edit 1:
So Conclusion is :
1) Use local broadcast mechanism to update the fragments present in ViewPager adapter
2) Use handler mechanism to refresh these fragments
3) if you want to blindly update these fragments once they are visible to users then do it inside onPageChangeListener of view pager method.
The answers helped me find the solution.
For future reference, I used a callback every time I used deleteItem(), and took a list of the loaded frags by using the method [FragmentHostingViewPager].getChildFragmentManager().getFragments()
Then I iterated through each fragment as long as each fragment was not null, and called a refresh() method on them.
So I currently have an app that has 4 tabs (fragments). They are fragments A,B,C,D, in that order.
Fragment A is the first view opened (along with B because viewPager loads the view before and after the current view).
When I click a button in Fragment A, it sends Data back to MainActivity and then sends that data out to Fragments B and C.
However, this is where the issue comes into play. Since Fragment B was already called, the View isn't updated once I click the button and send the data over, but Fragment C is because the view wasn't called before.
Is there any way that I can remedy this?
You can do it a few ways right.
Just set the data to the fragment and have it update its views
Have all the fragments like B and C register themselves to recieve data from the MainActivity and when MainActivity gets it's data set you tell all the registered receivers of the new data
Recreate the fragment
Use an event bus and tell all subsribers of the new data and MainActivity, Fragment B would get notified of new data. Fragment C would get its data when created by MainActivity
I think this list is pretty endless tbh
The key here is the fragments need to fetch the data from the actvitiy aswell as be updated by the activity. In which case you need to break your UI update behaviour out of onCreateView and into its own updateUI() function. updateUI(MyData) can then be called from onCreateView and also called in a setMyData() on the fragment. Just make sure you check the isAdded flag in setMyData.
This pretty much says it all:
http://developer.android.com/training/basics/fragments/communicating.html
I used a simple fragment communicator that allows the activity to call the fragment, and the same for a fragment to talk to the activity.
You can change the views with the new data based on calling the method from within the activity. The way I do it is set the fragments in the activity then pass them into the page adapter this way I can call the methods within the fragment and implement the fragmentcommunicator interface on the fragments.
You can honestly even avoid the interface if you want, but if you are going to include the same method in all the fragments to talk to them it is easiest.
If you show code, I can show you a quick example.
I have 2 fragments which are called from the action bar of an activity. Both are gridviews, the first one displays applications with a dedicated adapter, and the second one displays a file list with another adapter. My problem is that when I launch a file then when I back to my activity I switch from one fragment to another, when I come back to the previous one, its content disappears. And when I rotate tablet I have the some problem, because my Fragment restart so for this I think that removing fragment give the possibility to create a new Fragment up to date. How can I save and reload data in my fragment.
How can I manage to update the content of the first fragment while coming back from the second one ? And how to remove fragment after the rotation in order to recreate the Action with new Fragment? I asked this questions but I don't have any responses. the code is given below
If your data is just strings or integers, you can make use of shared preferences to store and retrieve data.
Solution to your first problem -how to save fragment state
Use setRetainInstance(true) in you fragments onCreate() *it prevents your fragment from destroying and hence recreating.
Add your fragment to back stack
declare your adapter globally in fragment and resuse it when you get back.
when, you get back to fragment its onCreateView() method will be called directly. hence initialize your adapter in onCreate() method and use it in onCreateView().
Solution to your second problem -how to update fragment content
For this you can use interface. create interface in your second fragment and implement it in your first fragment. prefer this doc for this,
http://www.vogella.com/tutorials/AndroidFragments/article.html#fragments_activitycommunication
So, I got the event in my fragment to pass to the activity, so how do I make it so the activity in turns, notifies fragment B to do something. I want to fragment B to populate a custom list when fragment A has a list item clicked on. So, it sends the event to the activity, now how do I get the activity to call events in fragment B?
One way to do it would be like this in your activity:
FragmentB fragmentB = (FragmentB)getFragmentManager().findFragmentById(R.id.fragmentBId);
fragmentB.performSomeTask();
This is of course assuming that you have a publicly accessibly method in FragmentB called performSomeTask();
Hope that helps!
The best practice is probably to create interfaces for both fragments and then have the activity implement the interfaces. You want to have good decoupling between fragments so that you can reuse them in other places.