Manera infalible de manejar Fragmento en el cambio de orientación

87
public class MainActivity extends Activity implements MainMenuFragment.OnMainMenuItemSelectedListener {

 @Override
 public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    FragmentManager fragmentManager = getFragmentManager();
    FragmentTransaction fragmentTransaction = fragmentManager
            .beginTransaction();

    // add menu fragment
    MainMenuFragment myFragment = new MainMenuFragment();
    fragmentTransaction.add(R.id.menu_fragment, myFragment);

    //add content
    DetailPart1 content1= new DetailPart1 ();
    fragmentTransaction.add(R.id.content_fragment, content1);
    fragmentTransaction.commit();

}
public void onMainMenuSelected(String tag) {
  //next menu is selected replace existing fragment
}

Necesito mostrar dos vistas de lista una al lado de la otra, el menú a la izquierda y su contenido a la derecha. De forma predeterminada, se selecciona el primer menú y su contenido se muestra en el lado derecho. El fragmento que muestra el contenido es el siguiente:

public class DetailPart1 extends Fragment {
  ArrayList<HashMap<String, String>> myList = new ArrayList<HashMap<String, String>>();
  ListAdapter adap;
  ListView listview;

  @Override
  public void onActivityCreated(Bundle savedInstanceState) {
      super.onActivityCreated(savedInstanceState);

       if(savedInstanceState!=null){
        myList = (ArrayList)savedInstanceState.getSerializable("MYLIST_obj");
        adap = new LoadImageFromArrayListAdapter(getActivity(),myList );
        listview.setAdapter(adap);
       }else{
        //get list and load in list view
        getlistTask = new GetALLListTasks().execute();
    }


     @Override
   public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {
    View v = inflater.inflate(R.layout.skyview_fragment, container,false);
           return v;
        }


     @Override
      public void onSaveInstanceState(Bundle outState) {
         super.onSaveInstanceState(outState);
          outState.putSerializable("MYLIST_obj", myList );
        }
    }

OnActivityCreated y onCreateView se llaman dos veces . Hay muchos ejemplos que usan fragmentos. Como soy un principiante en este tema, no puedo relacionar el ejemplo con mi problema. Necesito una forma infalible de manejar el cambio de orientación. NO he declarado android:configChangesen el archivo de manifiesto. Necesito que la actividad se destruya y se vuelva a crear para poder usar un diseño diferente en modo horizontal.

usuario1811741
fuente
Por lo general, los cambios de orientación de los fragmentos se solucionan sin necesidad de hacer nada. Entonces, ¿cuál es el problema que experimenta cuando cambia la orientación?
Alexander Kulyakhtin
Alex Necesito el fragmento de la clase DetailPart1 para mostrar el diseño con listView en modo vertical y el diseño con Grid View en modo horizontal. Para esto, necesito recrear el fragmento cada vez, pero no quiero volver a cargar los mismos registros, así que guárdelos en onSaveInstanceState. Pero el código anterior recrea DetailPart1 dos veces, necesito saber el código faltante que hace que funcione como se desea
user1811741
posible duplicado del ciclo de vida del fragmento
naXa

Respuestas:

132

Estás creando un nuevo fragmento cada vez que giras la pantalla en tu actividad, onCreate();pero también estás manteniendo los viejos con super.onCreate(savedInstanceState);. Entonces, tal vez establezca la etiqueta y encuentre el fragmento si existe, o pase el paquete nulo a super.

Esto me tomó un tiempo aprender y realmente puede ser una b ************************************************************************************************************************ ”” cuando se trabaja cuando se trabaja con cosas como viewpager.

Te recomiendo que leas sobre los fragmentos un tiempo adicional ya que se trata este tema exacto.

A continuación, se muestra un ejemplo de cómo manejar fragmentos en un cambio de orientación regular:

Actividad :

public class MainActivity extends FragmentActivity {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        if (savedInstanceState == null) {
            TestFragment test = new TestFragment();
            test.setArguments(getIntent().getExtras());
            getSupportFragmentManager().beginTransaction().replace(android.R.id.content, test, "your_fragment_tag").commit();
        } else {
            TestFragment test = (TestFragment) getSupportFragmentManager().findFragmentByTag("your_fragment_tag");
        }
    }
}

Fragmento :

public class TestFragment extends Fragment {

    public static final String KEY_ITEM = "unique_key";
    public static final String KEY_INDEX = "index_key";
    private String mTime;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_layout, container, false);

        if (savedInstanceState != null) {
            // Restore last state
            mTime = savedInstanceState.getString("time_key");
        } else {
            mTime = "" + Calendar.getInstance().getTimeInMillis();
        }

        TextView title = (TextView) view.findViewById(R.id.fragment_test);
        title.setText(mTime);

        return view;
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putString("time_key", mTime);
    }
}
Warpzit
fuente
gracias Warpzit por su esfuerzo, pero me alegrará si explica en el código sobre su punto. Cómo alterar mi código para manejar el cambio de orientación sin volver a cargar el fragmento.
user1811741
1
Por lo tanto, necesito que el diseño del fragmento se cambie en la orientación, pero no quiero volver a cargar todos los registros, lo que hice fue 1. agregar android: configchanges = "orientación" en el manifiesto 2. anular onConfigurationChanged en el fragmento y detectar la orientación y ocultar / mostrar vista de lista o vista de cuadrícula según la orientación. ¿Esta es la manera correcta?
user1811741
@ user1811741 actualizado con ejemplo. Espero que aclare todo.
Warpzit
@Warpzit ¿Cómo se puede manejar el mismo escenario en el caso de la implementación de ViewPager Fragment, ya que ViewPager se encarga de todos los fragmentos mostrados?
Código
1
@Shubh bueno, creo que viewpager maneja esto correctamente, si no, tendrá que anular la implementación de getItem para que se ajuste a sus necesidades. Espero que eso te haya indicado en la dirección correcta, si no
haces
21

Puede encontrar una buena pauta sobre cómo retener datos entre los cambios de orientación y la recreación de actividades en las pautas de Android .

Resumen:

  1. haz que tu fragmento sea retenible:

    setRetainInstance(true);
    
  2. Cree un nuevo fragmento solo si es necesario (o al menos tome datos de él)

    dataFragment = (DataFragment) fm.findFragmentByTag("data");
    
    // create the fragment and data the first time
    if (dataFragment == null) {
    
Sergej Werfel
fuente
nice Save my time wah
Arjun saini