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 returns null
. I've used the method replace in the FragmentTransaction
and I've finished it with commit()
, 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!
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:
Also, I would be more explicit when declaring instances, for example:
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:
Android Training - Replace
Android Reference - Replace
if you use
setRetainInstance(true)
than you can't usefindFragmentByTag()
inonCreate
from the Activity. Do it at onResumesee the documentation: setRetainInstance
We are also seeing this problem but the cause is slightly different. The suggested solution by https://stackoverflow.com/a/21170693/1035008 doesn't work for us.
And after reading the documentation about replace:
I realize that the
remove
call was not necessary since it is done byreplace
automatically. So after deleteft.remove(current)
, it works fine.Be sure you are adding or replacing the fragment in the proper way
Next statement will add the fragment but it will return null when using getFragmentManager().findFragmentByTag(tag):
This way it will work;
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
method so that your Fragment is resumed instead of destroyed as mentioned in the developer guides.
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!
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 bothfindFragmentById()
andfindFragmentByTag()
methods.