Interfaces, callbacks, listeners, llámalos como quieras, pero úsalos
Los callbacks funcionan de forma similar a un listener. Cuando tenemos que comunicar dos clases cuya visibilidad es unidireccional, como por ejemplo una activity con un adapter (en las que la activity contiene una instancia del adapter pero no en el otro sentido), tenemos un problema si necesitamos que la clase contenida se comunique con la clase que la contiene. La activity puede llamar a los métodos del adapter, pero el adapter no tiene un objeto activity (y pasárselo es altamente desaconsejable, ya que entorpece a la modularidad). ¿Qué sucede si necesitamos que, ante determinado evento en el adapter, se modifique una vista en la activity? En este caso podemos utilizar un bus de eventos o podemos crear un callback.Paso a paso
En este tutorial tendremos un campo de texto y un botón en un fragment. Al pulsar el botón, un interfaz enviará el texto a la activity, donde se mostrará. Para ello tendremos que seguir los siguientes pasos:- Crear una interfaz anidada en nuestra activity
- Instanciar la interfaz
- Crear un setter para la interfaz en el fragment
- Usar la interfaz ante determinado evento
1. Crear una interfaz anidada
Queremos recibir en nuestra activity un texto proveniente de un fragment, por lo que necesitamos crear una interfaz que tenga un método que reciba ese texto para poder utilizarlo. Ese método serárecibirTexto(String s)
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
public class MainActivity { private TextView tvMiTexto; @Override public void onCreate(Bundle savedInstanceState){ super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); tvMiTexto = (TextView) findaViewById(R.id.tv_mi_texto); getSupportFragmentManager().beginTransaction() .add(new MiFragment()) .commit(); } public interface ComunicacionInterfaz{ void recibirTexto(String s); } } |
2. Instanciar la interfaz
Podemos hacer esto de dos maneras: haciendo que MainActivity implemente la interfaz o creando una instancia anónima de la interfaz en la MainActivity. Sea como sea, debemos sobrescribir el métodorecibirTexto(String s)
indicando en él qué es lo que vamos a querer hacer con el texto recibido.
Implementando la interfaz
1 2 3 4 5 6 7 |
public class MainActivity implements ComunicacionInterfaz{ @Override public void recibirTexto(String s){ tvMiTexto.setText(s); } } |
Instancia anónima
1 2 3 4 5 6 7 8 9 10 |
public class MainActivity{ private ComuncacionInterfaz interfaz = new ComunicacionInterfaz(){ @Override public void recibirTexto(String s){ tvMiTexto.setText(s); } }; } |
recibirTexto(String s)
. En el cuerpo de este método debemos escribir el código de lo que queremos hacer con el texto recibido, que en este caso solo es mostrarlo.
3. Crear un setter para la interfaz en el fragment
Una vez implementada la interfaz, necesitamos pasársela al fragment para que este la pueda utilizar. Para ello creamos un setter en el fragment.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
public class MiFragment extends Fragment { private EditText etMiEditText; private Button btnMiBoton; private ComunicacionInterfaz interfaz; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) { ViewGroup root = (ViewGroup) inflater.inflate(R.layout.mi_fragment_layout, container, false); etMiEditText = (EditText) root.findViewById(R.id.et_mi_edit_text); btnMiBoton = (Button) root.findViewById(R.id.btn_mi_boton); return root; } // Setter public void setInterfaz(ComunicacionInterfaz interfaz){ this.interfaz = interfaz; } } |
1 2 3 4 5 |
MiFragment miFragment = new MiFragment(); miFragment.setInterfaz(interfaz); getSupportFragmentManager().beginTransaction() .add(new MiFragment()) .commit(); |
this
, en lugar de interfaz
.
4. Utilizar la interfaz
Ahora ya tenemos la instancia de la interfaz en el fragment, por lo que no nos queda más que llamarla cuando pulsemos el botón:
1 2 3 4 5 6 7 8 9 10 |
@Override public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) { btnMiBoton.setOnClickListener(newView.OnClickListener(){ @Override public void onClick(View v){ interfaz.recibirTexto(miEditText.getText()); } }; } |
recibirTexto()
, que se ejecuta en la MainActivity y que cambia el texto que aparece en esta.
5. Cuadro resumen
- Crea una interfaz en la clase contenedora
- Crea un objeto de la interfaz en la clase contenedora
- Crea un campo del tipo de la interfaz en la clase contenida
- Crea un método para recibir la interfaz en la clase contenida
- Asigna la interfaz a la clase contenida
- Utiliza la interfaz para avisar a la clase contenedora de que se ha producido un evento en la clase contenida
Exelente gracias.