with studio llamar from fragments desde con activity android interface fragment communication

studio - navigation view fragment android



Fundamentos de Android Fragments: ¿por qué? ¿Es esto conceptualmente incorrecto? (2)

Tengo una pregunta sobre "programación adecuada" en Android.

Actualmente estoy desarrollando una aplicación que usa fragmentos. Incluye fragmentos agregados dinámicamente a la actividad, fragmentos inflados de XML, fragmentos anidados de XML o agregados dinámicamente. Digamos, un poco de todo.

El concepto en el que se centra esta pregunta es el proceso de comunicación relacionado con los fragmentos. Entonces, he leído los documentos y esta no es la primera vez que trato de usar fragmentos.

El sentido común (y los documentos) dicen que si un Fragmento quiere hablar o comunicarse con su actividad, deberíamos usar una interfaz.

Ejemplo:

TestFragment

public class TestFragment extends Fragment { private TestFragmentInterface listener; public interface TestFragmentInterface { void actionMethod(); } @Override public void onViewCreated(View view, Bundle savedInstanceState) { if (getActivity() instanceof TestFragmentInterface) { listener = (TestFragmentInterface) getActivity(); } // sending the event if (listener != null) listener.actionMethod(); } }

TestActivity

public class Test implements TestFragmentInterface { @Override public void actionMethod() { .. } }

Todo bien aquí.

Esto mejora la reutilización, ya que mi TestFragment de esta manera puede interactuar con cualquier tipo de actividad, dado que Activity implementa la interfaz que declaro.

A la inversa, la actividad puede interactuar con el fragmento manteniendo una referencia y llamando a sus métodos públicos. Esta es también la forma sugerida para la comunicación fragmento a fragmento, usando la Actividad como un puente.

Esto es genial, pero a veces parece que usar una interfaz para esto es un poco "demasiado".

Pregunta A

En el escenario, los fragmentos que adjunto tienen un papel bastante específico, lo que significa que están hechos para esa actividad en particular y no se usarían de otra forma, ¿es conceptualmente incorrecto ignorar la implementación de la interfaz y simplemente hacer algo como

((TestActivity) getActivity().myCustomMethod();

?

Esto también va al escenario donde (no es mi caso, sino que simplemente lo tomo como "en su peor momento") mi actividad tiene que lidiar con una gran variedad de estos DIFERENTES fragmentos, lo que significa que debe implementar un método para cada fragmento que debe manejar . Esto lleva el código a un gran lío de "líneas potencialmente innecesarias".

Yendo más allá: todavía con el uso de fragmentos "enfocados", destinados a trabajar solo de cierta manera, ¿qué pasa con el uso de fragmentos anidados?

Los agregó como

public class TestFragment extends Fragment { private void myTestMethod() { NestedFragment nested = new NestedFragment(); getChildFragmentManager() .beginTransaction() .add(R.id.container, nested) .commit(); } }

esto une NestedFragment a TestFragment. Lo digo de nuevo, NestedFragment, al igual que TestFragment, debe usarse solo de esta manera, de otra manera no tiene sentido que funcione.

Volviendo a la pregunta, ¿cómo debo comportarme en esta situación?

Pregunta B

1) ¿debería proporcionar una interfaz en NestedFragment y hacer que TestFragments implemente NestedFragmentInterface? En este caso, actuaría de la siguiente manera

NestedFragment

public class NestedFragment extends Fragment { private NestedFragmentInterface listener; public interface NestedFragmentInterface { void actionMethodNested(); } @Override public void onViewCreated(View view, Bundle savedInstanceState) { if (getParentFragment() instanceof NestedFragmentInterface) { listener = (NestedFragmentInterface) getParentFragment(); } // sending the event if (listener != null) listener.actionMethodNested(); } }

2) debería (o podría) ignorar la interfaz, y solo llamar

getParentFragment().publicParentMethod();

?

3) ¿Debería crear la interfaz en NestedFragment, pero dejar que la actividad la implemente para que la actividad llame a TestFragment?

Pregunta C

En cuanto a la idea de utilizar la Actividad como un puente entre fragmentos, creo que está hecho para el ciclo de vida de manejo adecuado de todos estos objetos. ¿Sigue siendo viable hacer un fragmento directo a fragmento (utilizando la interfaz o llamar directamente a los métodos públicos) al tratar de manejar manualmente la excepción que el sistema podría arrojarme?


Haré todo lo posible para responder el muro de texto aquí :)

Pregunta A:

Los fragmentos están diseñados para ser módulos reutilizables que se pueden enchufar y reproducir con cualquier actividad. Debido a esto, la única forma correcta de interactuar con la actividad es hacer que la actividad herede de una interfaz que el fragmento comprenda.

public class MapFragment extends Fragment { private MapFragmentInterface listener; public interface MapFragmentInterface { //All methods to interface with an activity } @Override public void onViewCreated(View view, Bundle savedInstanceState) { // sending the event if (listener != null) listener.anyMethodInTheAboveInterface(); } }

Luego haga que la actividad implemente la interfaz

public class MainActivity extends Activity implement MapFragmentInterface{ //All methods need to be implemented here }

Esto permite que su fragmento se use con cualquier actividad siempre que la actividad implemente esta interfaz. La razón por la que necesita esta interfaz es porque el fragmento se puede usar con cualquier actividad. Llamar a un método como

((TestActivity) getActivity().myCustomMethod();

se basa en el hecho de que su fragmento solo puede funcionar dentro de una actividad de prueba y, por lo tanto, "rompe" las reglas de los fragmentos.

Pregunta B y C:

Asumiendo que está siguiendo las pautas correctas para los fragmentos y que son módulos independientes. Entonces nunca deberías tener una situación donde los fragmentos necesitan saberse el uno del otro. El 99% del tiempo que las personas piensan que necesitan fragmentos para comunicarse directamente, pueden volver a factorizar su problema a la situación que di más arriba mediante el uso de un patten MVC o algo similar. Haga que la actividad actúe como el controlador y diga los fragmentos cuando necesitan actualizar y luego cree un almacén de datos por separado.


Intentaré aclararlo un poco.

En primer lugar, considere su enfoque de configurar el oyente para el fragmento. No es bueno configurar al oyente en el método ViewCreated porque leeds a un oyente de restablecimiento excesivo se crea cualquier fragmento. Es suficiente configurarlo en el método de conexión.

Le conté sobre las líneas de código. Llévame a cuenta, es bueno tener BaseFragment implementado un comportamiento común en tu aplicación como configurar FragmentListener creando vista desde el recurso.

Y más que eso para reducir las líneas de código y obtener parte de la reutilización de código, puede usar genérico en BaseFragment. Así que mira el siguiente fragmento de código:

public abstract BaseFragment<T extends BaseFragmentListener> extends Fragment { T mListener; public void onAttach(Activity activity) { super.onAttach(activity); if (Activity instanceof T) mListener = (T) activity; } abstract int getLayoutResourceId(); @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View layout = inflater.inflate(getLayoutResourceId(), null); // you can use some view injected tools here, mb ButterKnife return layout; } }

Respuesta A (para la pregunta A):

Si tiene un fragmento de exactamente una actividad, debe decidir: "¿Realmente necesita utilizar Fragment aquí?". Pero mb es bueno tener un fragmento exactamente para una actividad para extraer alguna lógica de vista de la actividad y borrar la lógica base. Pero para borrar la lógica de la arquitectura base para su aplicación, use Listeners. Esto hará la vida más fácil para otros desarrolladores

Respuesta B: para los fragmentos anidados que necesita resolver, lo que necesitan para usar la actividad exacta o solo fragmentos y usarlo como un puente a otro sistema. Si sabes que el fragmento anidado se anidará todo el tiempo, debes declarar el fragmento principal como el oyente, de lo contrario, tienes que utilizar otro enfoque.

Aviso: como el enfoque base para comunicarse entre la parte diff de la aplicación puede usar eventos, intente también mirar el bus de eventos por ejemplo. Le da un enfoque común para la comunicación y puede extraer la lógica de llamar a los métodos personalizados de los oyentes y mucho más, toda la lógica se ubicará en el manejo de eventos y tendrá un sistema de mediación para la cooperación.

Respuesta C: explico parcialmente uno de los enfoques para cooperar entre fragmentos. El uso de un despachador de eventos evita que tengas muchos oyentes para todas las comunicaciones diferentes. Algunas veces es muy rentable.

O creo que es más útil usar Actividad, u otras vidas de clase en Actividad, para un mediador para la cooperación Fragmentos porque hay muchas situaciones de Fragmentos que cambian durante el ciclo de vida tanto de manejo como del sistema. Y enfoca toda esta lógica en un solo lugar y hace que tu código sea más claro.

Espero que mis consideraciones te ayuden.