¿Cuántas actividades vs fragmentos?

185

Introducción:

El patrón básico del "Tutorial de fragmentos" es más o menos así:

  1. En una tableta, tenga una lista a la izquierda, detalles a la derecha.
  2. Ambos son Fragmentsy ambos residen en el mismo Activity.
  3. En un teléfono, tenga una lista Fragmenten uno Activity.
  4. Lanzar una nueva Activitycon los detalles Fragment.

(p. ej., Android 3.0 Fragments API de Dianne Hackborn y Fragments API Guide )

En ambos dispositivos, la funcionalidad está en el Fragments. (sencillo)

En la tableta , toda la aplicación es 1Activity , en el teléfono , hay muchasActivities .


Preguntas:

  • ¿Hay alguna razón para dividir la aplicación del teléfono en muchas Activities?

Un problema con este método es que duplica una gran parte de la lógica en la tableta principal Activityy en el teléfono por separado Activities.

  • ¿No sería más fácil retener el modelo de 1 Actividad en ambos casos, usando la misma lógica de encendido Fragmentsy apagado (solo usando un diseño diferente)?

De esta manera, la mayor parte de la lógica reside en Fragmentssí mismos, y solo hay una única Activityduplicación de código.

También lo que he leído acerca de esto ActionBarSherlockes que parece funcionar mejor en Fragmentslugar de Activities(pero aún no he trabajado con él).

¿Los tutoriales están demasiado simplificados o me he perdido algo importante en este enfoque?


Hemos probado ambos enfoques con éxito en la oficina, pero estoy a punto de comenzar un proyecto más grande y quiero hacer las cosas lo más fáciles para mí.

Algunos enlaces a preguntas relacionadas:


Actualizaciones

Comencé la recompensa por una pregunta: todavía no estoy convencido de por qué necesito duplicar la lógica de mi aplicación en la actividad de mi tableta y en cada actividad del teléfono.

También encontré un artículo interesante de los chicos de Square, que bien vale la pena leer:

Richard Le Mesurier
fuente
38
+1 para una pregunta impresionante y bien escrita.
Siddharth Lele
eso es algo que me duele mucho hoy en día, actualmente estoy trabajando en una aplicación cuyo diseño incluye muchos fragmentos y estará disponible tanto en el teléfono como en la tableta, estoy buscando un camino intermedio, pero aún no pude encontrar ninguno ...
Nixit Patel
1
Sinceramente, no quiero ofenderte, pero creo que aceptaste lo que querías escuchar en lugar de la respuesta real. Google no recomienda la respuesta de Scuba y la publicación de blog que me gustó explica por qué.
pjco
1
@pjco Específicamente no estoy de acuerdo con tener onItemSelected()método en la Actividad. En mi aplicación "real", tengo muchas listas y sublistas. Este patrón sugiere que mi actividad de pestaña debe tener un onItemSelected()método para manejar cada una de las listas. Además, las actividades del teléfono deben tener la misma lógica duplicada dentro de cada una de ellas. En mi humilde opinión, es mucho mejor poner la lógica Elemento seleccionado en cada fragmento: no hay duplicación y prefiero esa forma de estructurar el código. Espero que esto ayude
Richard Le Mesurier
2
Actualmente estoy colgado de este dilema en el trabajo. Los fragmentos se cargan mucho más rápido que lanzar nuevas actividades, así que comencé a implementar una arquitectura de actividad única. Sin embargo, me encontré con un problema, que parece que no puedo encontrar una buena manera de admitir configuraciones de múltiples fragmentos sin hacer algo extravagante. Ver esta pregunta .
theblang

Respuestas:

41

Estoy de acuerdo en que los tutoriales están muy simplificados. Simplemente presentan, Fragmentspero no estoy de acuerdo con el patrón sugerido.

También estoy de acuerdo en que no es una buena idea duplicar la lógica de su aplicación en muchas Actividades (consulte el Principio DRY en wikipedia ).


Prefiero el patrón utilizado por la ActionBarSherlockaplicación Fragments Demo ( descargar aquí y código fuente aquí ). La demostración que más se acerca al tutorial mencionado en la pregunta es la llamada "Diseño" en la aplicación; o FragmentLayoutSupporten el código fuente.

En esta demostración, la lógica se ha movido del Activityy al Fragment. El TitlesFragmentrealmente contiene la lógica para cambiar Fragmentos. De esta manera, cada actividad es muy simple. Duplicar muchas actividades muy simples, donde ninguna de las lógicas está dentro de las actividades, lo hace muy simple.

Al poner la lógica en los Fragmentos, no hay necesidad de escribir el código más de una vez ; está disponible sin importar en qué Actividad se coloque el Fragmento. Esto lo convierte en un patrón más poderoso que el sugerido en el tutorial básico.

    /**
    * Helper function to show the details of a selected item, either by
    * displaying a fragment in-place in the current UI, or starting a
    * whole new activity in which it is displayed.
    */
    void showDetails(int index)
    {
        mCurCheckPosition = index;

        if (mDualPane)
        {
            // We can display everything in-place with fragments, so update
            // the list to highlight the selected item and show the data.
            getListView().setItemChecked(index, true);

            // Check what fragment is currently shown, replace if needed.
            DetailsFragment details = (DetailsFragment) getFragmentManager()
                .findFragmentById(R.id.details);
            if (details == null || details.getShownIndex() != index)
            {
                // Make new fragment to show this selection.
                details = DetailsFragment.newInstance(index);

                // Execute a transaction, replacing any existing fragment
                // with this one inside the frame.
                FragmentTransaction ft = getFragmentManager()
                    .beginTransaction();
                ft.replace(R.id.details, details);
                ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
                ft.commit();
            }

        }
        else
        {
            // Otherwise we need to launch a new activity to display
            // the dialog fragment with selected text.
            Intent intent = new Intent();
            intent.setClass(getActivity(), DetailsActivity.class);
            intent.putExtra("index", index);
            startActivity(intent);
        }
    }

Otra ventaja del patrón ABS es que no terminas con una actividad de tableta que contiene mucha lógica, y eso significa que ahorras memoria. El patrón tutorial puede conducir a una actividad principal muy grande en una aplicación más compleja; ya que necesita manejar la lógica de todos los fragmentos que se colocan en él en cualquier momento.

En general, no piense que es forzado a usar muchas actividades. Piense que tiene la oportunidad de dividir su código en muchos fragmentos y ahorrar memoria al usarlos.

Stephen Asherson
fuente
Gracias por una respuesta completa: he visto las demostraciones de ABS y creo que hay un montón de código bueno allí. Intentaré trasladar gran parte de mi lógica a los Fragmentos
Richard Le Mesurier,
La aplicación de demostración se mudó aquí: play.google.com/store/apps/…
Philipp E.
Creo que el patrón que está describiendo es del código de muestra original de Google: android-developers.blogspot.com/2011/02/… Creo que ActionBarSherlock acaba de portar el código de demostración de Google para usar clases de ABS.
Dan J
17

Creo que estás en el camino correcto. (Y sí, los tutoriales están demasiado simplificados).

En un diseño de tableta, puede usar una sola Actividad e intercambiar Fragmentos (en múltiples 'paneles'). Mientras está en un diseño de teléfono, puede usar una nueva Actividad para cada Fragmento.

Al igual que:

ingrese la descripción de la imagen aquí

Puede parecer mucho trabajo extra, pero al usar múltiples actividades para teléfonos, habilita el ciclo de vida básico de la actividad y el paso de intenciones. Esto también permite que el marco maneje todas las animaciones y el back-stack.

Para ayudar a reducir el código, puede usar BaseActivityay extender desde eso.

Entonces, si el usuario tiene una tableta que usaría MyMultiPaneFragActivityo algo similar. Esta actividad es responsable de administrar las devoluciones de llamada de los fragmentos y las intenciones de enrutamiento al fragmento correcto (como una intención de búsqueda)

Si el usuario tiene un teléfono, puede usar una Actividad regular con muy poco código y hacer que se extienda MyBaseSingleFragActivityo algo similar. Estas actividades pueden ser muy simples, 5-10 líneas de código (quizás incluso menos).

La parte difícil es enrutar los intentos y demás. * (Editar: ver más abajo).

Creo que la razón por la que esta es la forma recomendada es ahorrar memoria y reducir la complejidad y el acoplamiento. Si está intercambiando Fragmentos, el FragmentManagermantiene una referencia a ese Fragmento para la pila de reserva. También simplifica lo que debería estar 'ejecutándose' para el usuario. Esta configuración también desacopla las vistas, el diseño y la lógica en el Fragmento del ciclo de vida de la Actividad. De esta manera, un Fragmento puede existir en una sola actividad, junto con otro fragmento (dos paneles), o en una Actividad de tres paneles, etc.

* Uno de los beneficios de tener un enrutamiento de intención regular es que puede iniciar una Actividad explícitamente desde cualquier lugar de la pila de reserva. Un ejemplo podría ser en el caso de los resultados de búsqueda. (MySearchResults.class).

Lee aquí para más:

http://android-developers.blogspot.com/2011/09/preparing-for-handsets.html

Podría ser un poco más de trabajo inicial, porque cada fragmento debe funcionar bien en actividades separadas, pero generalmente vale la pena. Significa que puede usar archivos de diseño alternativos que definen diferentes combinaciones de fragmentos, mantener el código de fragmento modular, simplificar la administración de la barra de acción y dejar que el sistema maneje todo el trabajo de la pila posterior.

pjco
fuente
Aproveche la ventaja de MySearchResults: sugiere tener una forma diferente de responder a esa intención dependiendo del teléfono o la tableta. ¿Por qué es esto mejor que tener una sola actividad que responda en ambos casos? Sugiere que en la tableta no hay un enrutamiento de intención regular, por lo que debe resolver el problema de la tableta de todos modos. ¿Por qué no usar esa solución en el teléfono también?
Richard Le Mesurier
La ventaja aquí es que el código de su tableta puede esperar enrutarse a múltiples paneles. A veces querrás cambiar varios paneles con una sola intención. Como los resultados de una búsqueda a la izquierda con los detalles del primer elemento en el panel más grande a la derecha. Este código no sería portátil para un diseño único.
pjco
¿Por qué está bien cambiar fragmentos cuando hay muchos, pero si solo 1 fragmento es visible, no debo cambiar a otro fragmento?
Richard Le Mesurier
No estoy seguro de entender lo que quiere decir, pero para aclarar mi comentario anterior: a veces es posible que desee cambiar más de 1 fragmento al mismo tiempo en un diseño de varios fragmentos. Esto requiere código para cambiar 2 fragmentos, que no volvería a utilizar en un diseño de fragmento único
pjco
De nada :) favor de votar o aceptar si cree que la respuesta es útil
pjco
6

Aquí está la respuesta de Reto Meier sobre lo mismo, tomada de este video del curso de Fundamentos de Android de Udacity .

Hay varias razones por las que sería mejor dividir su aplicación en diferentes actividades.

  • Tener una sola actividad monolítica aumenta la complejidad de su código, lo que dificulta su lectura, prueba y mantenimiento.
  • Hace que crear y administrar filtros de intención sea mucho más difícil.
  • Aumenta el riesgo de acoplar firmemente componentes independientes.
  • Hace que sea mucho más probable que se presenten riesgos de seguridad si la actividad individual incluye tanto información confidencial como información segura para compartir.

Una buena regla general es crear una nueva actividad cada vez que cambie el contexto. Por ejemplo, mostrar un tipo diferente de datos y pasar de ver a ingresar datos.

Aditya Naique
fuente
Curiosamente, el título del video es "Por qué no solo usamos fragmentos"
Richard Le Mesurier
es un buen enfoque, estoy enfrentando toneladas de problemas con una sola actividad, múltiples fragmentos ... exp real probablemente
GvSharma 02 de
4

Un problema con este método es que duplica una gran parte de la lógica en la Actividad principal de la tableta y en las Actividades telefónicas separadas.

En el patrón maestro-detalle, hay dos actividades. Uno muestra ambos fragmentos en pantallas más grandes y solo el fragmento "maestro" en pantallas más pequeñas. El otro muestra el fragmento de "detalle" en pantallas más pequeñas.

Su lógica de detalle debe estar ligada al fragmento de detalle. Por lo tanto, no hay duplicación de código relacionada con la lógica de detalle entre actividades: la actividad de detalle simplemente muestra el fragmento de detalle, quizás pasando datos de un Intentextra.

Además, lo que he leído sobre ActionBarSherlock es que parece funcionar mejor con Fragmentos en lugar de Actividades (pero aún no he trabajado con él).

ActionBarSherlock no tiene más que ver con fragmentos que la barra de acción nativa, ya que ActionBarSherlock es puramente un backport de la barra de acción nativa.

CommonsWare
fuente
¿Qué piensa sobre la idea de una sola actividad?
theblang
@mattblang: siempre que tenga la navegación correcta, no hay problema con eso.
CommonsWare
1
He intentado refactorizar a una arquitectura de actividad única porque reemplazar un fragmento es mucho más rápido que lanzar una nueva actividad con ese mismo fragmento. Sin embargo, siento que me encuentro con demasiados inconvenientes, como este . La mayoría de los ejemplos que encuentro en línea, particularmente para configuraciones de múltiples fragmentos como detalles maestros, no usan una sola actividad. Así que estoy en un pequeño dilema.
theblang
0

Refiriéndose a la primera pregunta de "¿Hay alguna razón para dividir la aplicación del teléfono en muchas Actividades?" - Si. simplemente se reduce al espacio disponible, una tableta da más espacio a los desarrolladores, lo que permite a los desarrolladores poner más en una pantalla. Android nos dice que Actividades puede proporcionar una pantalla . Entonces, lo que puede hacer con 1 pantalla grande en una tableta es algo que puede tener que extenderse a través de múltiples pantallas en un teléfono, porque no hay suficiente espacio para todos los fragmentos.

EFlisio
fuente
Primera oración: "Una actividad es un componente de aplicación que proporciona una pantalla con la que los usuarios pueden interactuar para hacer algo". Veo un error en mi declaración original, no quise poner "son otra pantalla",
EFlisio