android - seguidos - Evite volver a crear la misma vista cuando realice el cambio de pestaña
hashtags mas seguidos en instagram (6)
Actualizar
Simplemente evitando este problema, usando ViewPager
lugar de la ActionBar
de ActionBar
.
Actual, tengo 2 Fragments
, que se puede cambiar a través de la pestaña de ActionBar
.
getSupportActionBar().setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
ActionBar.Tab newTab = getSupportActionBar().newTab();
newTab.setText("history");
newTab.setTabListener(new TabListenerHistoryFragment>(this, "history",
HistoryFragment.class));
@Override
public void onTabSelected(Tab tab, FragmentTransaction ft) {
// Check if the fragment is already initialized
if (mFragment == null) {
// If not, instantiate and add it to the activity
mFragment = Fragment.instantiate(mActivity, mClass.getName());
mFragment.setRetainInstance(true);
ft.add(android.R.id.content, mFragment, mTag);
} else {
// If it exists, simply attach it in order to show it
ft.attach(mFragment);
}
}
Me doy cuenta de que la primera vez que inicie mi Activity
(esta actividad contiene 2 fragmentos), los métodos de Fragment
s se llamarán en la siguiente secuencia.
onCreate -> onCreateView -> onStart
Cuando realizo el cambio de pestaña, y luego el cambio de pestaña al mismo fragmento, se volverán a llamar los siguientes métodos.
onCreateView -> onStart
Solo deseo conservar el mismo estado de vista de GUI, cuando la pestaña se está cambiando.
- Quiero que mi carta siga siendo ampliada al nivel anterior.
- Quiero que mi cuadro de desplazamiento horizontal permanezca en el nivel anterior.
- Quiero que mi lista continúe desplazándose a un nivel anterior.
- ...
Sé que puedo guardar / restaurar variables simples usando el siguiente método cuando se cambia de pestaña
Pero, eso no es algo que quiera, ya que mi estado de GUI es bastante difícil de describir dentro de un montón de valores primitivos.
Intento el siguiente enfoque. Por supuesto, no funcionará, ya que obtengo el siguiente error de tiempo de ejecución.
public class HistoryFragment extends Fragment {
View view = null;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
if (this.view != null) {
return this.view;
}
this.view = inflater.inflate(R.layout.history_activity, container, false);
}
}
java.lang.IllegalStateException: el hijo especificado ya tiene un padre. Debe llamar removeView () en el padre del niño primero.
Me doy cuenta de que el siguiente ejemplo de demostración es capaz de preservar su estado de GUI de fragmentos (por ejemplo, la posición del desplazamiento vertical de la lista) cuando hay un cambio de pestaña. Pero supongo, tal vez sea porque están usando ListFragment? Como no encuentro, realizan un manejo especial para preservar el estado de la GUI.
- com.example.android.apis.app.FragmentTabs
- com.example.android.apis.app.LoaderCursor.CursorLoaderListFragment
¿Puedo saber cómo puedo evitar volver a crear la misma vista cuando se realiza el cambio de pestañas?
Comencé a buscar una solución simple para esto hace muchas horas y finalmente tropecé con la respuesta de @roger que me ahorró mucho cabello ...
Cuando use ViewPager en otras implementaciones, simplemente podría llamar:
mViewPager.setOffscreenPageLimit(//number of pages to cache);
Entonces, estaba muy sorprendido de que me tomara tantas horas resolver esto. Sin embargo, el ejemplo que dio no fue del todo claro, así que para completar, aquí está el código que utilizo para los Fragmentos en mi FragmentTabHost
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
public class FragmentExample extends Fragment {
private View rootView;
public FragmentExample() {
}
@Override
public View onCreateView(final LayoutInflater inflater, final ViewGroup container, final Bundle savedInstanceState) {
if (rootView == null) {
rootView = inflater.inflate(R.layout.fragment_example_layout, container, false);
// Initialise your layout here
} else {
((ViewGroup) rootView.getParent()).removeView(rootView);
}
return rootView;
}
}
Busqué las siguientes frases clave que estoy agregando aquí, con la esperanza de poder salvar a otra persona de la frustración que acabo de experimentar.
FragmentTabHost guardar Estado del fragmento
FragmentTabHost vistas recreadas
FragmentTabHost caché Fragmentos
FragmentTabHost onCreateView Fragmento destruido
Enfrenté el mismo problema, pero lo que hice fue, antes de adjuntar o separar la ventana dentro de las devoluciones de llamada de ActionBar.TabListener, call
fragmentManager.executePendingTransactions();
esto resuelve el problema para mí
@Override
public void onTabelected(Tab tab, FragmentTransaction ft, FragmentManager fm) {
fm.executePendingTransactions(); // **execute the pending transactions before adding another fragment.
if (mFragment == null) {
mFragment = Fragment.instantiate(mContext, mFragmentName);
ft.replace(android.R.id.tabcontent, mFragment, mTag);
} else {
ft.attach(mFragment);
}
}
La siguiente solución funciona para mí. Impide que se llame a onCreateView de Fragment cuando se cambian las pestañas.
Activity onCreate debería agregar todos los fragmentos y ocultar todos excepto el de la primera pestaña:
ft.add(R.id.fragment_content, secondTabFragment);
ft.hide(secondTabFragment);
ft.add(R.id.fragment_content, firstTabFragment);
ft.show(firstTabFragment);
ft.commit();
currentFragment = firstTabFragment;
La actividad enTabSelected debe ocultar el fragmento actual y mostrar el fragmento correspondiente a la pestaña elegida.
ft.hide(currentFragment);
ft.show(chosenFragment);
ft.commit();
currentFragment = chosenFragment;
Tenga en cuenta que al cambiar la orientación del dispositivo, se reiniciará su Actividad y luego se recrearán sus Fragmentos. Puede evitar eso al agregar esta configChanges en su Manifiesto:
<activity android:configChanges="keyboardHidden|orientation" ...
Tuve el mismo problema e intenté seguir la sugerencia del mensaje de error. Probé el siguiente código, y funcionó para mí.
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle state) {
if (mMyView == null) {
mMyView = new MyView(getActivity());
} else {
((ViewGroup) mMyView.getParent()).removeView(mMyView);
}
return mPuzzleView;
}
View mMyView = null;
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle state) {
if (state == null) {
mMyView = new MyView(getActivity());
} else {
container.removeView(mMyView);
}
return mMyView;
}