Fragmento de Android oncreateview llamado en cambio de pestaña

He estado trabajando con Android por un tiempo, pero los fragmentos son un poco nuevos para mí (como probablemente lo son para la mayoría de las personas). De todos modos, tengo el siguiente código, y funciona bien. Tengo tres fragmentos, uno en cada pestaña. Me pregunto si es normal que se llame a onCreateView cada vez que cambio de pestaña, y ¿tiene sentido hacerlo? ¿No debería haber una manera de NO volver a dibujar el fragmento cada vez que cambia la pestaña?

Estoy convirtiendo esto desde una aplicación que tenía 3 actividades, una en cada pestaña, y parece un desperdicio recrear la vista cada vez que cambia la pestaña, cuando solía estar bien tener las vistas entre cambios de pestaña. .

Por cierto, este código tomado de: http://thepseudocoder.wordpress.com/2011/10/04/android-tabs-the-fragment-way/

public class Tabs extends FragmentActivity implements
    TabHost.OnTabChangeListener {

final String MAP_TAB = "Map";
final String IMAGES_TAB = "Images";
final String SETTINGS_TAB = "Settings";

TabHost mTabHost;
HashMap<String, TabInfo> mapTabInfo = new HashMap<String, TabInfo>();
TabInfo mLastTab = null;

private class TabInfo {
    private String tag;
    private Class clss;
    private Bundle args;
    private Fragment fragment;
    TabInfo(String tag, Class clazz, Bundle args) {
        this.tag = tag;
        this.clss = clazz;
        this.args = args;
    }

}

class TabFactory implements TabContentFactory {

    private final Context mContext;

    public TabFactory(Context context) {
        mContext = context;
    }

    public View createTabContent(String tag) {
        View v = new View(mContext);
        v.setMinimumWidth(0);
        v.setMinimumHeight(0);
        return v;
    }

}

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    requestWindowFeature(Window.FEATURE_NO_TITLE);
    setContentView(R.layout.main);

    initialiseTabHost(savedInstanceState);
    if (savedInstanceState != null)
        mTabHost.setCurrentTabByTag(savedInstanceState.getString("tab")); //set the tab as per the saved state
}

protected void onSaveInstanceState(Bundle outState) {
    outState.putString("tab", mTabHost.getCurrentTabTag()); //save the tab selected
    super.onSaveInstanceState(outState);
}

private void initialiseTabHost(Bundle args) {
    mTabHost = (TabHost)findViewById(android.R.id.tabhost);
    mTabHost.setup();
    TabInfo tabInfo;

    Tabs.addTab(this,
            mTabHost,
            mTabHost.newTabSpec(MAP_TAB).setIndicator(
                    MAP_TAB,
                    getResources().getDrawable(R.drawable.ic_tab_map_states)),
            ( tabInfo = new TabInfo(MAP_TAB, HMapFragment_NEW.class, args)));
    mapTabInfo.put(tabInfo.tag, tabInfo);

    Tabs.addTab(this,
            mTabHost,
            mTabHost.newTabSpec(IMAGES_TAB).setIndicator(
                    IMAGES_TAB,
                    getResources().getDrawable(R.drawable.ic_tab_gallery_states)),
            ( tabInfo = new TabInfo(IMAGES_TAB, ImageGridFragment.class, args)));
    mapTabInfo.put(tabInfo.tag, tabInfo);

    Tabs.addTab(this,
            mTabHost,
            mTabHost.newTabSpec(SETTINGS_TAB).setIndicator(
                    SETTINGS_TAB,
                    getResources().getDrawable(R.drawable.ic_tab_settings_states)),
            ( tabInfo = new TabInfo(SETTINGS_TAB, SettingsFragment.class, args)));
    mapTabInfo.put(tabInfo.tag, tabInfo);

    // Default to first tab
    this.onTabChanged(MAP_TAB);
    mTabHost.setOnTabChangedListener(this);
}

private static void addTab(Tabs activity, TabHost tabHost, TabHost.TabSpec tabSpec, TabInfo tabInfo) {
    // Attach a Tab view factory to the spec
    tabSpec.setContent(activity.new TabFactory(activity));
    String tag = tabSpec.getTag();

    // Check to see if we already have a fragment for this tab, probably
    // from a previously saved state.  If so, deactivate it, because our
    // initial state is that a tab isn't shown.
    tabInfo.fragment = activity.getSupportFragmentManager().findFragmentByTag(tag);
    if (tabInfo.fragment != null && !tabInfo.fragment.isDetached()) {
        FragmentTransaction ft = activity.getSupportFragmentManager().beginTransaction();
        ft.detach(tabInfo.fragment);
        ft.commit();
        activity.getSupportFragmentManager().executePendingTransactions();
    }

    tabHost.addTab(tabSpec);
}

public void onTabChanged(String tag) {
    TabInfo newTab = this.mapTabInfo.get(tag);
    // if they've clicked to change tabs
    if (mLastTab != newTab) {
        FragmentTransaction ft = this.getSupportFragmentManager().beginTransaction();
        if (mLastTab != null)
            if (mLastTab.fragment != null) ft.detach(mLastTab.fragment);
        if (newTab != null) {
            if (newTab.fragment == null) {
                newTab.fragment = Fragment.instantiate(this, newTab.clss.getName(), newTab.args);
                ft.add(R.id.realtabcontent, newTab.fragment, newTab.tag);
            } else ft.attach(newTab.fragment);
        }

        mLastTab = newTab;
        ft.commit();
        this.getSupportFragmentManager().executePendingTransactions();
    }
}
}

preguntado el 12 de junio de 12 a las 20:06

1 Respuestas

Hay 3 formas de eliminar un Fragmento de la vista:

  • Esconderlo (hide función en el objeto de transacción)
  • separarlo (detach función en el objeto de transacción)
  • eliminarlo (remove función en el objeto de transacción)

Si ocultar la vista se oculta, pero aún está en el diseño y debería permanecer intacta. Si tu despegar en él, la vista se elimina, pero FragmentManager sigue administrando el fragmento (y se volverá a crear en un cambio de configuración, por ejemplo). Si tu remove se elimina por completo de FragmentManager y su estado ya no se administrará.

Respondido el 12 de junio de 12 a las 20:06

Entonces, ¿tal vez debería intentar cambiar la llamada de desconexión anterior para ocultarla? - Joshkendrick

obviamente también necesitaba cambiar adjunto para agregar, ¡pero exactamente lo que quería! ¡Gracias! Exactamente por qué uso SO jaja - Joshkendrick

Creo que debería ser "show", en realidad. Primero agrega todas las pestañas una vez y luego las oculta y las muestra según sea necesario. - Timo Ohr

Tuve exactamente el mismo problema, pero necesito / quiero que se llame a onpause / onresume en mis fragmentos cuando se muestran u ocultan ... ¿hay alguna forma de lograr esto? Obtengo eso con adjuntar/separar, pero eso tiene un efecto secundario muy desafortunado con el onCreateView mencionado. - Mathias

yo tengo el mismo problema . ¿Puedes darme algún enlace de ejemplo? - somnoliento

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.