¿Cómo crear interfaz entre Fragment y el adaptador?

Tengo un fragmento con ListView , digamos MyListFragment y CursorAdapter personalizado. Estoy configurando onClickListener en este adaptador para el botón en la fila de la lista.

 public class MyListAdapter extends CursorAdapter { public interface AdapterInterface { public void buttonPressed(); } ... @Override public void bindView(final View view, final Context context, final Cursor cursor) { ViewHolder holder = (ViewHolder) view.getTag(); ... holder.button.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // some action // need to notify MyListFragment } }); } } public MyListFragment extends Fragment implements AdapterInterface { @Override public void buttonPressed() { // some action } } 

Necesito notificar el fragmento cuando se presiona el botón. ¿Cómo invocar esta interfaz?

Ayuda por favor.

Crea un nuevo constructor y una variable de instancia:

 AdapterInterface buttonListener; public MyListAdapter (Context context, Cursor c, int flags, AdapterInterface buttonListener) { super(context,c,flags); this.buttonListener = buttonListener; } 

Cuando se hace el Adaptador, la variable de instancia recibirá la referencia adecuada para mantener.

Para llamar al Fragmento desde el clic:

 public void onClick(View v) { buttonListener.buttonPressed(); } 

Al hacer el Adapter , también deberá pasar su Fragmento al Adaptador. Por ejemplo

 MyListAdapter adapter = new MyListAdapter (getActivity(), myCursor, myFlags, this); 

ya que this se referirá a su Fragmento, que ahora es una AdapterInterface .

Tenga en cuenta que en la orientación de los cambios del Fragmento, lo más probable es que se vuelva a crear. Si su Adaptador no es recreado, potencialmente puede mantener una referencia a un objeto inexistente, causando errores.

Usando Eventbus:

Ejemplos:

https://github.com/kaushikgopal/RxJava-Android-Samples/tree/master/app/src/main/java/com/morihacky/android/rxjava/rxbus

o

https://github.com/greenrobot/EventBus

Usando interfaces:

Comprendo la respuesta actual, pero necesitaba un ejemplo más claro. Aquí hay un ejemplo de lo que usé con un Adapter (RecyclerView.Adapter) y un Fragment .

Crear interfaz de Callback :

 public interface AdapterCallback { void onMethodCallback(); } 

Al pasar en Callback / Fragment :

Esto implementará la interface que tenemos en nuestro Adapter . En este ejemplo, se llamará cuando el usuario haga clic en un elemento en RecyclerView .

En tu Fragment :

 public class MyFragment extends Fragment implements AdapterCallback { private MyAdapter mMyAdapter; @Override public void onMethodCallback() { // do something } @Override public void onCreate(final Bundle savedInstanceState) { super.onCreate(savedInstanceState); this.mMyAdapter = new MyAdapter(this); // this class implements callback } } 

Use la Callback de Callback en su adaptador:

En el Fragment , iniciamos nuestro Adapter y pasamos esto como un argumento para el constructor. Esto iniciará nuestra interface para nuestro método de callback. Puede ver que usamos nuestro método de callback para los clics del usuario.

 public class MyAdapter extends RecyclerView.Adapter { private AdapterCallback mAdapterCallback; public MyAdapter(AdapterCallback callback) { this.mAdapterCallback = callback; } @Override public void onBindViewHolder(final MyAdapter.ViewHolder viewHolder, final int i) { // simple example, call interface here // not complete viewHolder.itemView.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { mAdapterCallback.onMethodCallback(); } }); } } 

o use el Fragment en su adaptador:

 public class MyAdapter extends RecyclerView.Adapter { private AdapterCallback mAdapterCallback; public MyAdapter(Fragment fragment) { try { this.mAdapterCallback = ((AdapterCallback) fragment); } catch (ClassCastException e) { throw new ClassCastException("Fragment must implement AdapterCallback."); } } @Override public void onBindViewHolder(final MyAdapter.ViewHolder viewHolder, final int i) { // simple example, call interface here // not complete viewHolder.itemView.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { try { mAdapterCallback.onMethodCallback(); } catch (ClassCastException exception) { // do something } } }); } } 

Siga los 2 pasos a continuación para recibir una callback del Adapter en el Fragment (or Activity)

Primero: en su Adapter

 public class ListAdapter extends RecyclerView.Adapter < RecyclerListAdapter.ItemViewHolder > { ... private ListAdapterListener mListener; public interface ListAdapterListener { // create an interface void onClickAtOKButton(int position); // create callback function } public RecyclerListAdapter(Context mContext, ArrayList < Items > listItems, ListAdapterListener mListener) { // add the interface to your adapter constructor ... this.mListener = mListener; // receive mListener from Fragment (or Activity) } ... public void onBindViewHolder(final ItemViewHolder holder, final int position) { holder.btnOK.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { // use callback function in the place you want mListener.onClickAtOKButton(position); } }); ... } ... } 

Segundo: en su Fragment (or Activity) , hay 2 formas para implementar el método de callback

Camino 1

  public MyListFragment extends Fragment { ... public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { ... ListAdapter adapter = new ListAdapter(getActivity(), listItems, new ListAdapter.ListAdapterListener() { @Override public void onClickAtOKButton(int position) { Toast.makeText(getActivity(), "click ok button at" + position, Toast.LENGTH_SHORT).show(); } }); ... } } 

Camino 2

 public MyListFragment extends Fragment implements ListAdapter.ListAdapterListener { ... public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { ListAdapter adapter = new ListAdapter (getActivity(), listItems, this); ... } @Override public void onClickAtOKButton(int position) { Toast.makeText(getActivity(), "click ok button at" + position, Toast.LENGTH_SHORT).show(); } } 

Esto es muy similar a la forma en que una actividad y un fragmento deberían comunicarse. En el constructor de su adaptador, pase una referencia de su fragmento, transfiéralo a su interfaz y simplemente llame a yourReference.buttonPressed () en su método onClick.

una solución para NPE es primero hacer conctractor en tu Fragmento así

 public MyFragment MyFragment(){ return this; } 

a continuación, inicialice su oyente es un adaptador como ese

 Lisener lisener = new MyFragment(); 

Haz un constructor así:

  public MyAdapter(Activity activity,AlertMessageBoxOk alertMessageBoxOk) { this.mActivity = activity; mAlertMessageBoxOk = alertMessageBoxOk; } 

llamar a la interfaz desde el adaptador usar cualquier evento

 mAlertMessageBoxOk.onOkClick(5); 

después de eso, implementa la interfaz AlertMessageBoxOk en tu fragmento como este,

 class MyFragment extends Fragment implements AlertMessageBoxOk { @Override public void onOkClick(int resultCode) { if(resultCode==5){ enter code here } } }