This what I have
XListActivity.class
It inflates LinearLayout and creates one Fragment, YListFragment
YListFragment.class
Inflates LsitView from xml and setup a adapter which extends base adapter
Now on some event (e.g. onClick), I want to reuse same fragment and ListView whith different set of data.
If I handle OnClick() event in XListActivity then I don't have reference of ListView and Adapter created in yListFragment. I need them to empty adapter. I want to avoid static references.
How can I achieve this?
You can get your fragment by tag or id using the FragmentManager.
YListFragment fragment = (YListFragment)getFragmentManager().findFragmentByTag("ylistfragment");
fragment.somePublicMethodInYListFragment();
Activity -> Fragment and Fragment -> Activity communication guidelines are outlined here
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
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."
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.
Sorry for bad English.
I have BaseFragment. it contains Search View and View Pager and View pager has three fragement like Fragment A,B,C
Fragment B has Listview.
so whenever i am doing search i got search response in Base fragment now what i want to do is push these response to fragment B listview inside viewpager. when every time search action perform and need to refresh listview.
You can get an instance of the fragment you want by calling Fragment manager like this:
CustomFragment fragment = (CustomFragment) getSupportFragmentManager().findFragmentById(R.id.fragment_a);
and then you can call any methods of the fragment like this:
fragment.update(data);
But make sure you check the fragment is not null before calling its methods.
So, there is a button in a ListFragment. The onCLick method of the button is implemented in the MainActivity(not sure if it is a proper solution, but it is what it is). When I click the button the AlertDialog pops up and when I choose one of the dialog options it changes the dataset my fragment is working with.
The problem is when the AlertDialog disappears, my ListFragment is still displaying old data.
Is there any way to update my ListFragment from the MainActivity?
I've tried making certain ListFragment methods static so that they could be called from the main activity, but those methods use non-static fields, etc. and thus cannot be static.
You should be able to update ListFragments by calling notifyDataSetChanged() on it's adapter (assuming that your adapter derives from BaseAdapter or any of it's subclasses). The easiest way to do this would probably be set an an DialogInterface.OnDismissListener on your dialog.
myDialog.setOnDismissListener(new DialogInterface.OnDismissListener() {
#Override
public void onDismiss(DialogInterface dialog){
myBaseAdapter.notifyDataSetChanged();
}
});
You can either keep the reference to the Adapter or get it directly from the ListFragment depending on your implementation.
So, I declared an adapter of my ListFragment fragment as static, as well as the I declared a list from which this adapter is being filled - as static.
From the main activity I do this:
ListFragment.item.add(mChosenFilePath);
ListFragment.fileList.notifyDataSetChanged();
where:
item - is a list that contains the elements that are to be displayed
mChosenFilePath - path of file that has been added into the item as a result of the dialog
fileList - is my adapter
Set a tag, or id for the fragment. You can then call a method directly on the fragment from the Activity:
Fragment myne = findFragmentByTag( "MyFragment" );
MyFragment target = (MyFragment) myne;
target.refresh(); // 'Refresh' method to be declared by MyFragment implementation
There are three possible solutions.
Listen for the click in your fragment instead of the Activity.
Set a listener on the cancel button of your dialog, and reload the fragment as needed.
Add your fragment with a tag, get it from the manager by that tag, and call the appropriate method.