Cómo implementar OnFragmentInteractionListener

Tengo una aplicación de asistente generada con un cajón de navegación en Android Studio 0.8.2

Creé un fragmento y lo agregué con newInstance () y recibí este error:

com.domain.myapp E / AndroidRuntime: EXCEPCIÓN FATAL: main java.lang.ClassCastException: com.domain.myapp.MainActivity@422fb8f0 debe implementar OnFragmentInteractionListener

No puedo encontrar en ninguna parte cómo implementar este OnFragmentInteractionListener ?? ¡No se puede encontrar incluso en la documentación de SDK de Android!

MainActivity.java

import android.app.Activity; import android.app.ActionBar; import android.app.Fragment; import android.app.FragmentManager; import android.os.Bundle; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.support.v4.widget.DrawerLayout; public class MainActivity extends Activity implements NavigationDrawerFragment.NavigationDrawerCallbacks { /** * Fragment managing the behaviors, interactions and presentation of the navigation drawer. */ private NavigationDrawerFragment mNavigationDrawerFragment; /** * Used to store the last screen title. For use in {@link #restreActionBar()}. */ private CharSequence mTitle; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mNavigationDrawerFragment = (NavigationDrawerFragment) getFragmentManager().findFragmentById(R.id.navigation_drawer); mTitle = getTitle(); // Set up the drawer. mNavigationDrawerFragment.setUp( R.id.navigation_drawer, (DrawerLayout) findViewById(R.id.drawer_layout)); } @Override public void onNavigationDrawerItemSelected(int position) { // update the main content by replacing fragments FragmentManager fragmentManager = getFragmentManager(); switch (position) { case 0: fragmentManager.beginTransaction() .replace(R.id.container, PlaceholderFragment.newInstance(position + 1)) .commit(); break; case 1: fragmentManager.beginTransaction() .replace(R.id.container, AboutFragment.newInstance("test1", "test2")) .commit(); break; // this crashes the app case 2: fragmentManager.beginTransaction() .replace(R.id.container, BrowseQuotesFragment.newInstance("test1", "test2")) .commit(); break; // this crashes the app } } public void onSectionAttached(int number) { switch (number) { case 1: mTitle = getString(R.string.title_section1); break; case 2: mTitle = getString(R.string.title_section2); break; case 3: mTitle = getString(R.string.title_section3); break; } } public void restreActionBar() { ActionBar actionBar = getActionBar(); actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD); actionBar.setDisplayShowTitleEnabled(true); actionBar.setTitle(mTitle); } @Override public boolean onCreateOptionsMenu(Menu menu) { if (!mNavigationDrawerFragment.isDrawerOpen()) { // Only show items in the action bar relevant to this screen // if the drawer is not showing. Otherwise, let the drawer // decide what to show in the action bar. getMenuInflater().inflate(R.menu.main, menu); restreActionBar(); return true; } return super.onCreateOptionsMenu(menu); } @Override public boolean onOptionsItemSelected(MenuItem item) { // Handle action bar item clicks here. The action bar will // automatically handle clicks on the Home/Up button, so long // as you specify a parent activity in AndroidManifest.xml. int id = item.getItemId(); if (id == R.id.action_settings) { return true; } return super.onOptionsItemSelected(item); } /** * A placeholder fragment containing a simple view. */ public static class PlaceholderFragment extends Fragment { /** * The fragment argument representing the section number for this * fragment. */ private static final String ARG_SECTION_NUMBER = "section_number"; /** * Returns a new instance of this fragment for the given section * number. */ public static PlaceholderFragment newInstance(int sectionNumber) { PlaceholderFragment fragment = new PlaceholderFragment(); Bundle args = new Bundle(); args.putInt(ARG_SECTION_NUMBER, sectionNumber); fragment.setArguments(args); return fragment; } public PlaceholderFragment() { } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View rootView = inflater.inflate(R.layout.fragment_main, container, false); return rootView; } @Override public void onAttach(Activity activity) { super.onAttach(activity); ((MainActivity) activity).onSectionAttached( getArguments().getInt(ARG_SECTION_NUMBER)); } } 

}

Las respuestas publicadas aquí no ayudaron, pero el siguiente enlace sí:

http://developer.android.com/training/basics/fragments/communicating.html

Definir una interfaz

 public class HeadlinesFragment extends ListFragment { OnHeadlineSelectedListener mCallback; // Container Activity must implement this interface public interface OnHeadlineSelectedListener { public void onArticleSelected(int position); } @Override public void onAttach(Activity activity) { super.onAttach(activity); // This makes sure that the container activity has implemented // the callback interface. If not, it throws an exception try { mCallback = (OnHeadlineSelectedListener) activity; } catch (ClassCastException e) { throw new ClassCastException(activity.toString() + " must implement OnHeadlineSelectedListener"); } } ... } 

Por ejemplo, se llama al siguiente método en el fragmento cuando el usuario hace clic en un elemento de la lista. El fragmento usa la interfaz de callback para entregar el evento a la actividad principal.

 @Override public void onListItemClick(ListView l, View v, int position, long id) { // Send the event to the host activity mCallback.onArticleSelected(position); } 

Implementar la interfaz

Por ejemplo, la siguiente actividad implementa la interfaz del ejemplo anterior.

 public static class MainActivity extends Activity implements HeadlinesFragment.OnHeadlineSelectedListener{ ... public void onArticleSelected(int position) { // The user selected the headline of an article from the HeadlinesFragment // Do something here to display that article } } 

Actualización para API 23: 8/31/2015

El método onAttach(Activity activity) ahora está en desuso en android.app.Fragment , el código debe actualizarse a onAttach(Context context)

 @Override public void onAttach(Context context) { super.onAttach(context); } @Override public void onStart() { super.onStart(); try { mListener = (OnFragmentInteractionListener) getActivity(); } catch (ClassCastException e) { throw new ClassCastException(getActivity().toString() + " must implement OnFragmentInteractionListener"); } } 

Para aquellos de ustedes que todavía no entienden después de leer la respuesta de @meda, esta es mi explicación concisa y completa para este tema:

Digamos que tienes 2 Fragmentos, Fragment_A y Fragment_B que se generan automáticamente desde la aplicación. En la parte inferior de los fragmentos generados, vas a encontrar este código:

 public class Fragment_A extends Fragment { //rest of the code is omitted public interface OnFragmentInteractionListener { // TODO: Update argument type and name public void onFragmentInteraction(Uri uri); } } public class Fragment_B extends Fragment { //rest of the code is omitted public interface OnFragmentInteractionListener { // TODO: Update argument type and name public void onFragmentInteraction(Uri uri); } } 

Para solucionar el problema, debe agregar el método onFragmentInteraction en su actividad, que en mi caso se denomina MainActivity2 . Después de eso, debe implementar todos los fragmentos en MainActivity esta manera:

 public class MainActivity2 extends ActionBarActivity implements Fragment_A.OnFragmentInteractionListener, Fragment_B.OnFragmentInteractionListener, NavigationDrawerFragment.NavigationDrawerCallbacks { //rest code is omitted @Override public void onFragmentInteraction(Uri uri){ //you can leave it empty } } 

PD: En resumen, este método podría usarse para comunicarse entre fragmentos. Para aquellos de ustedes que quieran saber más acerca de este método, consulte este enlace .

Mira tu Fragment autogenerado creado por Android Studio. Cuando creó el nuevo Fragment , Studio apagó un montón de código para usted. En la parte inferior de la plantilla generada automáticamente hay una definición de interfaz interna llamada OnFragmentInteractionListener . Tu Activity necesita implementar esta interfaz. Este es el patrón recomendado para que su Fragment notifique su Activity de eventos para que pueda tomar las medidas adecuadas, como cargar otro Fragment . Consulte esta página para obtener detalles, busque la sección “Crear devoluciones de llamada de eventos para la actividad”: http://developer.android.com/guide/components/fragments.html

Para aquellos de ustedes que visiten esta página buscando más aclaraciones sobre este error, en mi caso la actividad que hace la llamada al fragmento necesita tener 2 implementos en este caso, como este:

 public class MyActivity extends Activity implements MyFragment.OnFragmentInteractionListener, NavigationDrawerFragment.NaviationDrawerCallbacks { ...// rest of the code } 

Deberías intentar eliminar el siguiente código de tus fragmentos

  try { mListener = (OnFragmentInteractionListener) activity; } catch (ClassCastException e) { throw new ClassCastException(activity.toString() + " must implement OnFragmentInteractionListener"); } 

La interfaz / escucha es un valor predeterminado creado para que su actividad y fragmentos puedan comunicarse más fácilmente

Además de la respuesta de @ user26409021, si ha agregado un ItemFragment, el mensaje en el ItemFragment es;

 Activities containing this fragment MUST implement the {@link OnListFragmentInteractionListener} interface. 

Y debe agregar en su actividad;

 public class MainActivity extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener, ItemFragment.OnListFragmentInteractionListener { //the code is omitted public void onListFragmentInteraction(DummyContent.DummyItem uri){ //you can leave it empty } 

Aquí el ítem ficticio es lo que tienes en la parte inferior de tu ItemFragment

En lugar de contexto de uso de la actividad, funciona para mí.

 @Override public void onAttach(Context context) { super.onAttach(context); try { mListener = (OnFragmentInteractionListener) context; } catch (ClassCastException e) { throw new ClassCastException(context.toString() + " must implement OnFragmentInteractionListener"); } } 

OnFragmentInteractionListener es la implementación predeterminada para gestionar la comunicación de fragmentos a actividades. Esto puede implementarse según sus necesidades. Supongamos que si necesita ejecutar una función en su actividad durante un momento particular dentro de su fragmento, puede hacer uso de este método de callback. Si no necesita tener esta interacción entre su activity alojamiento y fragment , puede eliminar esta implementación.

En resumen, debe implement el oyente en su actividad de alojamiento de fragmentos si necesita la interacción fragmento-actividad como esta

 public class MainActivity extends Activity implements YourFragment.OnFragmentInteractionListener {..} 

y tu fragmento debería tenerlo definido así

 public interface OnFragmentInteractionListener { // TODO: Update argument type and name void onFragmentInteraction(Uri uri); } 

también proporciona definición para void onFragmentInteraction(Uri uri); en tu actividad

o simplemente elimine la inicialización del listener de su fragmento en onAttach si no tiene ninguna interacción fragmento-actividad

Solo una adición:

OnFragmentInteractionListener maneja la comunicación entre Activity y Fragment usando una interfaz (OnFragmentInteractionListener) y Android Studio lo crea de manera predeterminada, pero si no necesitas comunicarte con tu actividad, puedes simplemente obtener su paseo.

El objective es que pueda adjuntar su fragmento a múltiples actividades y seguir reutilizando el mismo enfoque de comunicación (cada actividad podría tener su propio OnFragmentInteractionListener para cada fragmento).

Pero y si estoy seguro de que mi fragmento se adjuntará a un solo tipo de actividad y quiero comunicarme con esa actividad?

Entonces, si no quiere usar OnFragmentInteractionListener debido a su verbosidad, puede acceder a sus métodos de actividad usando:

 ((MyActivityClass) getActivity()).someMethod() 

Me gustaría agregar la destrucción del oyente cuando el fragmento se separa de la actividad o se destruye.

 @Override public void onDetach() { super.onDetach(); mListener = null; } 

y cuando se usa el nuevo método onStart () con Contexto

 @Override public void onDestroy() { super.onDestroy(); mListener = null; } 

Solo ve a tu fragmento Activity y elimina todo el método … en lugar de eso, usa el método createview.

su fragmento solo tiene en el método oncreateview eso es todo.

// solo este método implementa otro método delete

  @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View rootView = inflater.inflate(R.layout.fragment_main, container, false); return rootView; } 

y asegúrese de que su diseño sea una demostración para usted.