Comunicación entre un fragmento y una actividad-mejores prácticas


Esta pregunta es principalmente para solicitar opiniones sobre la mejor manera de manejar mi aplicación. Tengo tres fragmentos manejados por una actividad. El fragmento A tiene un elemento clickable la foto y el fragmento B tiene 4 elementos clickables los botones. El otro fragmento solo muestra detalles cuando se hace clic en la foto. Estoy usando ActionBarSherlock.

Captura de pantalla

Los botones adelante y atrás deben cambiar la foto a las poses siguiente o anterior, respectivamente. Podría seguir con la foto y los botones en el mismo fragmento, pero quería mantenerlos separados en caso de que quisiera reorganizarlos en una tableta.

Necesito un consejo - ¿debo combinar Fragmentos A y B? Si no, tendré que averiguar cómo implementar una interfaz para 3 elementos seleccionables.

Consideré usar Roboguice, pero ya estoy extendiendo el uso de SherlockFragmentActivity por lo que es un no ir. Vi mención de Otto, pero no vi buenos tutoriales sobre cómo incluirlo en un proyecto. ¿Qué haces ¿crees que las mejores prácticas de diseño deberían serlo?

También necesito ayuda para averiguar cómo comunicarse entre un fragmento y una actividad. Me gustaría mantener algunos datos "globales" en la aplicación, como el pose id. ¿Hay algún código de ejemplo que pueda ver además de la información del desarrollador de Android? Eso no es tan útil.

Por cierto, ya estoy almacenando toda la información sobre cada pose en una base de datos SQLite. Esa es la parte fácil.

Author: Vadim Kotov, 2013-01-10

9 answers

La forma más fácil de comunicarse entre su actividad y los fragmentos es utilizando interfaces. La idea es básicamente definir una interfaz dentro de un fragmento A dado y dejar que la actividad implemente esa interfaz.

Una vez que haya implementado esa interfaz, puede hacer lo que quiera en el método que anula.

La otra parte importante de la interfaz es que tienes que llamar al método abstracto desde tu fragmento y recordar enviarlo a tu actividad. Debería coger una ClassCastException si no se hace correctamente.

Hay un buen tutorial en Simple Developer Blog sobre cómo hacer exactamente este tipo de cosas.

Espero que esto haya sido útil para usted!

 64
Author: Eenvincible,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-03-30 21:59:58

El método sugerido para la comunicación entre fragmentos es usar callbacks\listeners que son administrados por su actividad principal.

Creo que el código de esta página es bastante claro: http://developer.android.com/training/basics/fragments/communicating.html

También puede hacer referencia a la aplicación IO 2012 Schedule, que está diseñada para ser una aplicación de referencia de facto. Se puede encontrar aquí: http://code.google.com/p/iosched /

También, aquí hay una pregunta con buena info: Cómo pasar datos entre fragmentos

 22
Author: Booger,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:18:20

Se implementa mediante la interfaz de devolución de llamada: En primer lugar tenemos que hacer una interfaz:

public interface UpdateFrag {
     public void updatefrag();
    }

En la actividad haga el siguiente código:

UpdateFrag updatfrag ;
public void updateApi(UpdateFrag listener) {
        updatfrag = listener;
   }

Desde el evento desde donde la devolución de llamada tiene que disparar en la actividad:

updatfrag.updatefrag();

En Fragment implementar la interfaz en CreateView hacer el siguiente código:

 ((Home)getActivity()).updateApi(new UpdateFrag() {
                @Override
                public void updatefrag() {
                   .....your stuff......
                }
            });
 8
Author: Jyoti,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-09-03 17:48:14

Hice una biblioteca de anotaciones que puede hacer el reparto por ti. mira esto. https://github.com/zeroarst/callbackfragment /

@CallbackFragment
public class MyFragment extends Fragment {

    @Callback
    interface FragmentCallback {
       void onClickButton(MyFragment fragment);
    }    
    private FragmentCallback mCallback;

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.bt1
                mCallback.onClickButton(this);
                break;
            case R.id.bt2
                // Because we give mandatory = false so this might be null if not implemented by the host.
                if (mCallbackNotForce != null)
                mCallbackNotForce.onClickButton(this);
                break;
        }
    }
}

Luego genera una subclase de tu fragmento. Y solo agrégalo a FragmentManager.

public class MainActivity extends AppCompatActivity implements MyFragment.FragmentCallback {

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

        getSupportFragmentManager().beginTransaction()
            .add(R.id.lo_fragm_container, MyFragmentCallbackable.create(), "MY_FRAGM")
            .commit();
    }

    Toast mToast;

    @Override
    public void onClickButton(MyFragment fragment) {
        if (mToast != null)
            mToast.cancel();
        mToast = Toast.makeText(this, "Callback from " + fragment.getTag(), Toast.LENGTH_SHORT);
        mToast.show();
    }
}
 3
Author: Arst,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-06-22 08:14:13

Hay varias maneras de comunicarse entre actividades, fragmentos, servicios, etc. La obvia es comunicarse usando interfaces. Sin embargo, no es una forma productiva de comunicarse. Tienes que implementar los oyentes, etc.

Mi sugerencia es usar un bus de eventos. Event bus es una implementación de patrón de publicación / suscripción.

Puede suscribirse a eventos en su actividad y luego puede publicar esos eventos en sus fragmentos, etc.

Aquí en mi entrada de blog puede encontrar más detalles sobre este patrón y también un proyecto de ejemplo para mostrar el uso.

 2
Author: Gunhan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-04-08 13:45:57

No estoy seguro de entender realmente lo que quieres hacer, pero la forma sugerida de comunicarse entre fragmentos es usar callbacks con la Actividad, nunca directamente entre fragmentos. Ver aquí http://developer.android.com/training/basics/fragments/communicating.html

 1
Author: alex,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-01-09 23:08:20

Para comunicarse entre un Activity y Fragments, hay varias opciones, pero después de mucha lectura y muchas experiencias, descubrí que se podría resumir de esta manera:{[36]]}

  • Activity quiere comunicarse con child Fragment = > Simplemente escriba métodos públicos en su clase Fragment, y deje que Activity los llame
  • Fragment quiere comunicarse con el padre Activity = > Esto requiere un poco más de trabajo, ya que el enlace oficial de Android https://developer.android.com/training/basics/fragments/communicating sugiere, sería una gran idea para definir un interface que será implementado por el Activity, y que establecerá un contrato para cualquier Activity que quiere comunicar con que Fragment. Por ejemplo, si tiene FragmentA, que quiere comunicarse con cualquier activity que lo incluya, entonces defina el FragmentAInterface que definirá qué método puede llamar el FragmentA para el activities que decida usarlo.
  • A Fragment quiere para comunicarse con otros Fragment = > Este es el caso donde se obtiene la situación más 'complicada'. Dado que potencialmente podría necesitar pasar datos de FragmentA a FragmentB y viceversa, eso podría llevarnos a definir 2 interfaces, FragmentAInterface que serán implementadas por FragmentB y FragmentAInterface que serán implementadas por FragmentA. Eso empezará a complicar las cosas. E imaginen si tienen unos cuantos Fragmentmás en el lugar, e incluso el padre activity quiere comunicarse con ellos. Bueno, este caso es un momento perfecto para establecer un ViewModel compartido para el activity y es fragment s. Más información aquí https://developer.android.com/topic/libraries/architecture/viewmodel . Básicamente, necesita definir una clase SharedViewModel, que tenga todos los datos que desea compartir entre activity y fragments que necesitarán comunicar datos entre ellos.

El caso ViewModel, hace las cosas bastante más simples al final, ya que no tiene que agregar lógica adicional que ensucie las cosas en el código y desordenado. Además, le permitirá separar la recopilación (a través de llamadas a una base de datos SQLite o una API) de los datos Controller (activities y fragments).

 1
Author: Carlos Alberto Martínez Gadea,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-08-10 15:33:29

Puede crear declarar una interfaz pública con una declaración de función en el fragmento e implementar la interfaz en la actividad. Luego puede llamar a la función desde el fragmento.

 0
Author: Jacob Abraham,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-12-31 12:06:22

Estoy usando Intents para comunicar acciones a la actividad principal. La actividad principal es escucharlos anulando onNewIntent (Intent intent). La actividad principal traduce estas acciones a los fragmentos correspondientes, por ejemplo.

Así que puedes hacer algo como esto:

public class MainActivity extends Activity  {

    public static final String INTENT_ACTION_SHOW_FOO = "show_foo";
    public static final String INTENT_ACTION_SHOW_BAR = "show_bar";


   @Override
   protected void onNewIntent(Intent intent) {
        routeIntent(intent);
   }

  private void routeIntent(Intent intent) {
       String action = intent.getAction();
       if (action != null) {               
            switch (action) {
            case INTENT_ACTION_SHOW_FOO:
                // for example show the corresponding fragment
                loadFragment(FooFragment);
                break;
            case INTENT_ACTION_SHOW_BAR:
                loadFragment(BarFragment);
                break;               
        }
    }
}

Luego dentro de cualquier fragmento para mostrar el fragmento foo:

Intent intent = new Intent(context, MainActivity.class);
intent.setAction(INTENT_ACTION_SHOW_FOO);
// Prevent activity to be re-instantiated if it is already running.
// Instead, the onNewEvent() is triggered
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP);
getContext().startActivity(intent);
 0
Author: Pepster,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-12-16 11:17:58