findFragmentByTag() returns null after perform a FragmentTransaction using replace() method
Solution 1
I've fixed it! I called getSupportFragmentManager().executePendingTransactions()
after doing the transaction and it worked! After calling that method I can get the fragment using both findFragmentById()
and findFragmentByTag()
methods.
Solution 2
if you use setRetainInstance(true)
than you can't use findFragmentByTag()
in onCreate
from the Activity. Do it at onResume
see the documentation: setRetainInstance
Solution 3
I'll start by apologising since I'm still very new myself...
I think the problem may be in the declaration of the fragmentTag static String not properly getting access from the class's instances, just change that line to:
private final static String FRAGMENT_TAG = "FRAGMENTB_TAG"; // using uppercase since it's a constant
Also, I would be more explicit when declaring instances, for example:
public void buttonListener(View v){
FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.replace(R.id.right_container, new FragmentB(), FRAGMENT_TAG);
ft.commit();
FragmentB fragB = (FragmentB) getFragmentManager().findFragmentByTag(FRAGMENT_TAG);
fragB.testView();
}
I hope you get this sorted, as I seen this question posted earlier and was surprised that it hadn't got any activity yet.
Also, here are a couple of links to the android documentation on replace:
Solution 4
I had the same problem and realized that there is a really simple way to fix this. When using a tag please do make sure to add the
fragmentTransaction.addToBackStack(null);
method so that your Fragment is resumed instead of destroyed as mentioned in the developer guides.
If you don't call addToBackStack() when you perform a transaction that removes a fragment, then that fragment is destroyed when the transaction is committed and the user cannot navigate back to it. Whereas, if you do call addToBackStack() when removing a fragment, then the fragment is stopped and is later resumed if the user navigates back.
You can find this at the end of this section.
Every time I tried to reference back to my created Fragment, it turns out it had already been destroyed so I lost about 30 minutes trying to figure out why my Fragment was not being found through a simple findFragmentByTag();
call.
Hope this helps!
Guillermo Barreiro
Telecommunications Engineer, technology enthusiast since I was a children, self-taught, always willing to learn new things and develop projects to make people’s life easier. Sports, music, and traveling lover.
Updated on June 13, 2020Comments
-
Guillermo Barreiro almost 4 years
My Android app consists three fragments: A, B and C. They're loaded in the two containers defined in the
MainActivity
layout.When the app is started, it shows the fragmentA loaded in the left_container and the fragmentC in the right_container.
If you press the button in the fragmentA, a
FragmentTransaction
changes FragmentC by FragmentB.At the moment everything OK. But the trouble appears when I try to get a reference to the loaded fragmentB using
findFragmentByTag()
, because it returnsnull
. I've used the method replace in theFragmentTransaction
and I've finished it withcommit()
, but there isn't way to call FragmentB method. My code:MainActivity.java:
public class MainActivity extends Activity{ static String fragmentTag = "FRAGMENTB_TAG"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //Adds the left container's fragment getFragmentManager().beginTransaction().add(R.id.left_container, new FragmentA()).commit(); //Adds the fragment A to the left container //Adds the right container's fragment getFragmentManager().beginTransaction().add(R.id.right_container, new FragmentC()).commit(); //Adds the Fragment C to the right container } /** * Called when the button "Activate Fragment B" is pressed */ public void buttonListener(View v){ FragmentTransaction ft = getFragmentManager().beginTransaction(); ft.replace(R.id.right_container, new FragmentB(),fragmentTag); //Replaces the Fragment C previously in the right_container with a new Fragment B ft.commit(); //Finishes the transaction //!!HERE THE APP CRASHES (java.lang.NullPointerException = findFragmentByTag returns null ((FragmentB) getFragmentManager().findFragmentByTag(fragmentTag)).testView(); } }
FragmentB.java:
public class FragmentB extends Fragment { public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { return inflater.inflate(R.layout.fragment_b, container,false); } /** * Gets a reference to the text_fragment_b TextView and calls its method setText(), changing "It doesn't work" text by "It works!" */ public void testView(){ TextView tv = (TextView)getView().findViewById(R.id.text_fragment_b); tv.setText("It works!"); } }
activity_main.xml:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="horizontal" > <FrameLayout android:id="@+id/left_container" android:layout_width="0px" android:layout_weight="50" android:layout_height="match_parent"/> <FrameLayout android:id="@+id/right_container" android:layout_width="0px" android:layout_weight="50" android:layout_height="match_parent"/> </LinearLayout>
fragment_b.xml:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:layout_margin="5sp"> <TextView android:id="@+id/text_fragment_b" android:text="It doesn't works!" android:layout_width="match_parent" android:layout_height="wrap_content"/> </LinearLayout>
Please help me! I'm a beginner in Android development!
-
Guillermo Barreiro over 10 yearsIt didn't work. The method findFragmentByTag() still returns null despite the changes that you've said me.
-
Kenny164 over 10 yearsTry replacing the FRAGMENT_TAG with just normal string values then, e.g
ft.replace(R.id.right_container, new FragmentB(), "fragmentB");
-
Guillermo Barreiro over 10 yearsNeither works. I cant' find an error in my code, and I've tried lots of changes, but I'm still getting a null fragment in the method
findFragmentByTag()
-
Guillaume almost 10 yearsI'd rather override onAttachFragment and act when the fragment is ready.
-
IgorGanapolsky over 9 yearsI don't see how this solves the problem, or where to put executePendingTransactions().
-
IgorGanapolsky over 9 years@Kenny164 FRAGMENT_TAG is a String constant anyway. What is the point of replacing it??
-
Guillermo Barreiro over 9 years@igor-ganapolsky You have to put
executePendingTransactions()
after calling the.commit()
method of the FragmentTransaction. This forces the system to execute the transaction if it hadn't been done yet. -
Sami Eltamawy almost 9 yearsIt didn't work for me. Add it after the
commit()
and still have anull
value fragment -
ToolmakerSteve over 8 yearsIf not using v4-compatibility support library, I think you should do
getFragmentManager()
.executePendingTransactions() rather thangetSupportFragmentManager()
.executePendingTransactions(). -
Jonas over 7 yearsDoesn't work for me. Getting "FragmentManager is already executing transactions" exception in some cases when calling executePendingTransactions() and some other fragments get messed up.
-
Hephaestus about 7 yearsNo joy. Still getting null even with
getFragmentManager().executePendingTransactions();
placed after the.commit()
call. -
Shn almost 6 yearsFor those who added executePendingTransactions() and didn't have success, just try adding the Fragment object to your class and reference that in your method that executes the fragment transaction. It's not perfect, but it's a workaround. Make sure you update the Fragment object each time you replace/add a fragment to avoid the object being null...
-
Georgiy Chebotarev over 4 yearsI didn't understand why this answer is correct)) It doesn;t help for findFragmentByTag. Where is your full answer and real result?