I have a nav fragment and a content fragment. I want to be able to pass a bundle, and reload the fragment based on fragment interactions. I've seen people say use .setArguments(), but it's not letting me use said method. Any advice?
public void onStockFragmentInteraction(String stock) {
Bundle bundle = new Bundle();
bundle.putString("stock", stock);
getFragmentManager()
.beginTransaction()
.replace(R.id.content, new StoryFragment())
.addToBackStack(null)
.commit();
}
setArguments is a method of Fragment not of FragmentManager
StoryFragment f = new StoryFragment()
f.setArguments(bundle);
getFragmentManager()
.beginTransaction()
.replace(R.id.content, f)
.addToBackStack(null)
.commit();
keep a reference to the fragment and call setArguments on the instance before submitting it on the transaction
Related
Which is the better approach for fragment transaction in terms of optimization and performance?
1.
ParentFragment-
FragmentManager fm = getSupportFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
ft.replace(R.id.container, ChildFragment.newInstance(arrayList));
ft.commit();
ChildFragment-
public static ChildFragment newInstance(ArrayList<PlanModel> bPlanModels) {
ChildFragment fragment = new ChildFragment();
Bundle bundlearrayList = new Bundle();
bundlearrayList.putSerializable(AppConstant.ARRAYlIST, bPlanModels);
fragment.setArguments(bundlearrayList);
return fragment;
}
2.
ParentFragment-
FragmentManager fm = getSupportFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
ft.replace(R.id.container, ChildFragment.newInstance(arrayList));
ft.commit();
ChildFragment-
private ArrayList<BrowsePlanModel> bPlanModels;
public ChildFragment(ArrayList<PlanModel> bPlanModels)
{
this.bPlanModels=bPlanModels
}
public static ChildFragment newInstance(ArrayList<PlanModel> bPlanModels)
{
ChildFragment fragment = new ChildFragment(bPlanModels);
return fragment;
}
3.
ParentFragment-
FragmentManager fm = getSupportFragmentManager();
FragmentTransaction ft = fm.beginTransaction();.
ChildFragment fragment = new ChildFragment();
Bundle bundlearrayList = new Bundle();
bundlearrayList.putSerializable(AppConstant.ARRAYlIST, bPlanModels);
fragment.setArguments(bundlearrayList);
ft.replace(R.id.container, fragment);
ft.commit();
All approaches are incorrect.
In the first one array is stored to bundle as serializable which leads to lack in performance. You should change it to parcelable array.
bundlearrayList.putParcelableArrayList(AppConstant.ARRAYlIST, bPlanModels);
In this case your list objects have to implement Parcelable interface.
Of course the first one could be right, if you put parcelable array instead of serializable, also use builder for more readability:
getSupportFragmentManager().beginTransaction()
.replace(R.id.container, ChildFragment.newInstance(arrayList))
.commit();
Second one is completely wrong, because default constructor should be left in the Fragment, otherwise system won't be able to restore its state and throws an exception on attempt. Also if you'll add it, it will be also wrong, because initial arguments won't be restored because them don't present in input bundle.
Third one is bad encapsulated if you tried to fill bundle in the beginning fragment, because filling a bungle is an inner realization.
By the way, in real projects i prefer to encapsulate responsibility of transactions from beginning fragment to a particular TransactionManager class. The approach is easy maintained with di frameworks, like dagger2
Hi I have A RecycleView Adapter and A button. I want that button to start a Fragment. I can start an activity but not a fragment. I have tried this Onclick method for my Button
#Override
public void onClick(View v) {
Bundle bundle = new Bundle();
bundle.putParcelable("event", events.get(getLayoutPosition()));
Fragment fragment = new EditEventDetailFragment();
fragment.setArguments(bundle);
fragment.getFragmentManager().beginTransaction().replace(R.id.contentMainDrawer,fragment).commit();
}
But have error invoke null object (contentMainDrawer) is my Main activity content_layout.
Any help is much appreciate. The Fragment host recycle view is call from Mainactivity
Use below code for replace fragment
Fragment fragment = new EditEventDetailFragment();
FragmentManager fragmentManager = getActivity().getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.contentMainDrawer, fragment, "tag").commit();
if you are using this code inside adapter than replace getActivity() to ((Activity) context).
Hi I have found 2 answer that help whoever needed. The answer is to use the Activity that host the calling fragment. Many thanks #Mohit Suthar
Bundle bundle = new Bundle();
bundle.putParcelable("event", events.get(getLayoutPosition()));
Fragment fragment = new EditEventDetailFragment();
fragment.setArguments(bundle);
FragmentManager fragmentManager = ((MainActivity) context).getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.contentMainDrawer, fragment, "tag").commit();
I'm adding a Fragment to my Activity like this:
getSupportFragmentManager()
.beginTransaction()
.add(R.id.frame_container, fragment)
.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN)
.addToBackStack(fragment.getClass().getName())
.commit();
But when I want to find the Fragment using a FragmentManager it's returning null:
Fragment oldFragment = (Fragment) getSupportFragmentManager().findFragmentByTag(fragment.getClass().getName());
You try to find it by tag, but you haven't given it any tag
if you want to give it a tag, do it like this
getSupportFragmentManager()
.beginTransaction()
.add(R.id.frame_container, fragment, "tagABC")
.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN)
.addToBackStack(fragment.getClass().getName())
.commit();
and then you can get it with
Fragment oldFragment = (Fragment) getSupportFragmentManager().findFragmentByTag("tagABC");
BTW, you should correct your question title, the problem has nothing related to backstack.
I have a Fragment called MyFrag and I create two instance of this Fragment, frag1 and frag2. In frag1 I register a click listener, and in the callback of this click listener I want to perform a FragmentTransaction and replace frag1 with frag2.
I managed to replace Fragments in an Activity but Fragments don't have the getSupportFragmentManager() method. This is the code I am using:
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction transaction = fragmentManager.beginTransaction();
transaction.replace(R.id.fragment_container, new Flashcard_Fragment(false, 3));
transaction.commit();
Use getFragmentManager() in the Fragment instead of getSupportFragmentManager(). getSupportFragmentManager() is only used in the FragmentActivity. Try this:
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction transaction = fragmentManager.beginTransaction();
transaction.replace(R.id.fragment_container, new Flashcard_Fragment(false,3));
transaction.commit();
Also be sure that Flashcard_Fragment has an empty constructor as well! The OS requires Fragments to have an empty public constructor.
You can just call getFragmentManager() in your Fragment.
The FragmentManager you get from getFragmentManager() is used to replace/add Fragments to the Activity.
The FragmentManager you get from getChildFragmentManager() is used to replace/add Fragments inside of other Fragments.
So it seems that you just need to use getFragmentManager().
getFragmentManager().beginTransaction()
.replace(R.id.graph_fragment_holder, new GraphFragment(), "GRAPH_FRAGMENT")
.commit();
getFragmentManager().beginTransaction()
.replace(R.id.list_fragment_holder, new ListFragment(), "LIST_FRAGMENT")
.commit();
//getFragmentManager().executePendingTransactions();
GraphFragment graphFragment = (GraphFragment) getFragmentManager().findFragmentByTag("GRAPH_FRAGMENT");
graphFragment.setData(data);
ListFragment listFragment = (ListFragment) getFragmentManager().findFragmentByTag("LIST_FRAGMENT");
listFragment.setData(data);
I've supplied a tag so I'm not sure why findFragmentByTag() returns null.
What I've tried from reading other questions:
this.setRetainInstance(true) in the oncreate of both fragments.
Both fragment constructors are empty public fragmentName(){}.
tried executePendingTransactions after adding the fragments.
tried add instead of replace on the fragments (edited)
I was confused about this for a long time. First, you need to save the fragment you are replacing by pushing it onto the back stack. The tag you supply is put on the fragment you are adding, not the one you are pushing onto the back stack. Later, when you do push it onto the back stack, that tag goes with it. Here's code with objects broken out to make it easier to trace. You must call 'addToBackStack' before 'commit'.
GraphFragment grFrag = new GraphFragment();
FragmentTransaction tr = getSupportFragmentManager().beginTransaction();
tr.replace(R.id.fragment_container, grFrag, "GRAPH_FRAGMENT");
// grFrag is about to become the current fragment, with the tag "GRAPH_FRAGMENT"
tr.addToBackStack(null);
// 'addToBackStack' also takes a string, which can be null, but this is not the tag
tr.commit();
// any previous fragment has now been pushed to the back stack, with it's tag
ListFragment liFrag = new ListFragment();
FragmentTransaction tr = getSupportFragmentManager().beginTransaction();
tr.replace(R.id.fragment_container, liFrag, "LIST_FRAGMENT");
// liFrag is is about to become the current fragment, with the tag "LIST_FRAGMENT"
tr.addToBackStack(null);
tr.commit();
// 'grFrag' has now been pushed to the back stack, with it's tag being "GRAPH_FRAGMENT"
Call getFragmentManager().executePendingTransactions() after fragment transaction.
getFragmentManager()
.beginTransaction()
.replace(R.id.container, new ExampleFragment(), "YOUR TAG HERE");
.commit();
//after transaction you must call the executePendingTransaction
getFragmentManager().executePendingTransactions();
//now you can get fragment which is added with tag
ExampleFragment exampleFragment = getFragmentManager().findFragmentByTag("YOUR TAG HERE");
I was having the same problem of findFragmentByTag() always returning null.
Eventually I tracked it down, I was overriding onSaveInstanceState() in my Activity but not calling super. As soon as I fixed that findFragmentByTag() returned the Fragment as expected.
You can use
fragmentTransaction.addToBackStack(yourFragmentTag);
After that you can reuse it with
getSupportFragmentManager().findFragmentByTag(yourFragmentTag);
Answered here, just need to call getSupportFragmentManager().executePendingTransactions(); after your findByTag or findById
In my case I had to create a class level FragmentManager object and then use it instead of using getSupportFragmentManager() directly.
public class Main extends BaseActivity {
FragmentManager fragmentManager;
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.fragmain);
fragmentManager = getSupportFragmentManager();
initFrag1();
}
private void initFrag1() {
String name = Frag1.class.getSimpleName();
if (fragmentManager.findFragmentByTag(name) == null) {
fragmentManager.beginTransaction()
.add(R.id.frag_container, new Frag1(), name)
.addToBackStack(name)
.commit();
}
}
}