tutorial studio implement how fragments example create android android-fragments fragmenttransaction

example - how to implement fragments in android studio



findFragmentByTag() devuelve nulo después de realizar un FragmentTransaction utilizando el método replace() (5)

Mi aplicación para Android consta de tres fragmentos: A, B y C. Se cargan en los dos contenedores definidos en el diseño de MainActivity .

Cuando se inicia la aplicación, muestra el fragmento A cargado en el contenedor izquierdo y el fragmentoC en el contenedor derecho .

Si presiona el botón en el fragmento A , una FragmentTransaction cambia FragmentC por FragmentB .

Por el momento todo está bien. Pero el problema aparece cuando trato de obtener una referencia al fragmento cargado findFragmentByTag() usando findFragmentByTag() , porque devuelve null . He usado el método replace en FragmentTransaction y lo he terminado con commit() , pero no hay forma de llamar al método FragmentB . Mi código:

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>

¡Por favor, ayúdame! ¡Soy un principiante en el desarrollo de Android!


¡Lo arreglé! Llamé a getSupportFragmentManager().executePendingTransactions() después de hacer la transacción y ¡funcionó! Después de llamar a ese método, puedo obtener el fragmento utilizando los findFragmentById() y findFragmentByTag() .


Asegúrese de agregar o reemplazar el fragmento de la manera correcta

La siguiente instrucción agregará el fragmento pero devolverá nulo cuando use getFragmentManager (). FindFragmentByTag (tag):

transaction.add(R.id.mainContent, fragment);


De esta forma funcionará;

transaction.add(R.id.mainContent, fragment, tag);


Empezaré por disculparme ya que todavía soy muy nuevo ...

Creo que el problema puede estar en la declaración de fragmentTag static String que no obtiene acceso de las instancias de la clase, simplemente cambie esa línea a:

private final static String FRAGMENT_TAG = "FRAGMENTB_TAG"; // using uppercase since it''s a constant

Además, sería más explícito al declarar instancias, por ejemplo:

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(); }

Espero que lo solucionen, ya que he visto esta pregunta publicada anteriormente y me sorprendió que todavía no haya tenido actividad.

Además, aquí hay un par de enlaces a la documentación de Android en reemplazo:

Entrenamiento de Android - Reemplazar

Referencia de Android - Reemplazar


También estamos viendo este problema, pero la causa es ligeramente diferente. La solución sugerida por https://.com/a/21170693/1035008 no funciona para nosotros.

void updateFragment(Fragment newFragment) { FragmentTransaction ft = getFragmentManager().beginTransaction(); // We have these 2 lines extra Fragment current = getChildFragmentManager().findFragmentByTag(fragmentTag); if (current != null) { ft.remove(current); } ft.replace(R.id.right_container, newFragment, 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(); }

Y después de leer la documentación sobre el reemplazo:

Reemplace un fragmento existente que se agregó a un contenedor. Esto es esencialmente lo mismo que llamar a eliminar (Fragment) para todos los fragmentos agregados actualmente que se agregaron con el mismo containerViewId y luego agregar (int, Fragment, String) con los mismos argumentos que aquí.

Me doy cuenta de que la llamada de remove no era necesaria ya que se realiza mediante el replace automático. Entonces, después de eliminar ft.remove(current) , funciona bien.


si usa setRetainInstance (true), entonces no puede usar findFragmentByTag () en onCreate desde Activity. Hazlo en onResume

ver la documentación: setRetainInstance