Android: el mejor enfoque para pasar datos entre fragmentos de viewpager

Tengo 3 fragmentos en una actividad de ViewPager. Los 3 fragmentos tienen campos de entrada. Aquí estoy tratando de pasar dos primeros fragmentos de datos a tercer fragmento. He leído algunos mensajes aquí y la mayoría de ellos sugirieron utilizar interfaces (es decir, para pasar los datos a través de la actividad de los padres) También he pasado por este enlace http://developer.android.com/training/basics/fragments/communicating.html

Interfaz: el uso de interfaces es un buen enfoque cuando estamos enviando datos a través de algún evento de usuario. Aquí estoy tratando de enviar datos sin ningún evento de usuario. Por lo tanto, pensé en onPause () ya que onPause () siempre se llama. Pero ViewPager funciona de forma diferente. Cuando se carga un fragmento, también se cargan los fragmentos adyacentes. Sería exitoso pasar datos entre el primer fragmento al tercer fragmento. Pero onPause () del segundo fragmento no será llamado a menos que esté navegando a algún fragmento que no esté adyacente a él (que en mi caso no está allí)

Setter / Getters: He leído en pocos posts personas diciendo que no usar setter / getters (todavía no he entendido la razón todavía) ¿Son getters y setters diseño pobre? Consejos contradictorios vistos

Paquete: No he considerado esto todavía. Dado que estoy de nuevo confundido aquí, ¿cómo pasar los datos usando bundle. (Dentro de qué método debo enviar los datos y cómo?)

Lo siento si mi pregunta suena tonto. Estoy tratando de entender fragmentos y me gustaría saber la mejor manera de pasar los datos entre fragmentos en viewpager. Gracias de antemano.

TabPAgerAdapter ->

package com.jbandroid.model; import com.jbandroid.fragment.LocationInfoFragment; import com.jbandroid.fragment.PersonalInfoFragment; import com.jbandroid.fragment.PostInfoFragment; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentPagerAdapter; public class TabsPagerAdapter extends FragmentPagerAdapter { public TabsPagerAdapter(FragmentManager fm){ super(fm); } @Override public Fragment getItem(int index) { switch(index) { case 0 : //PostInfoFragment return new PostInfoFragment(); case 1 : //LocationInfoFragment return new LocationInfoFragment(); case 2 : //PersonalInfoFragment return new PersonalInfoFragment(); } return null; } @Override public int getCount() { // get item count - equal to number of tabs return 3; } } 

ViewPagerActivity ->

  package com.jbandroid; public class SubmitPostActivity extends FragmentActivity implements ActionBar.TabListener,PostInfoFragment.setPostInfo,LocationInfoFragment.setLocationInfo{ private ViewPager viewpager; private ActionBar actionBar; private TabsPagerAdapter mAdapter; FragmentManager manager; PersonalInfoFragment frag; List<String> location; /*private MenuItem myActionMenuItem; private Button myActionButton;*/ //Tab titles private String[] tabs = {"Post Info" , "Location Info" , "Personal Info" }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.action_submit_post); viewpager = (ViewPager) findViewById(R.id.pager); actionBar = getActionBar(); manager = getSupportFragmentManager(); mAdapter = new TabsPagerAdapter(getSupportFragmentManager()); //viewpager.setOffscreenPageLimit(2); viewpager.setAdapter(mAdapter); //actionBar.setHomeButtonEnabled(false); actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS); for (String tab : tabs){ actionBar.addTab(actionBar.newTab().setText(tab).setTabListener(this)); } if(savedInstanceState != null){ actionBar.setSelectedNavigationItem( savedInstanceState.getInt("tab",0)); } /** * on swiping the viewpager make respective tab selected * */ viewpager.setOnPageChangeListener(new OnPageChangeListener() { @Override public void onPageSelected(int position) { // on changing the page // make respected tab selected actionBar.setSelectedNavigationItem(position); } @Override public void onPageScrolled(int arg0, float arg1, int arg2) { } @Override public void onPageScrollStateChanged(int arg0) { } }); } @Override protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); outState.putInt("tab", getActionBar().getSelectedNavigationIndex()); } @Override public void onTabReselected(Tab tab, FragmentTransaction ft) { } @Override public void onTabSelected(Tab tab, FragmentTransaction ft) { // on tab selected // show respected fragment view viewpager.setCurrentItem(tab.getPosition()); } @Override public void onTabUnselected(Tab tab, FragmentTransaction ft) { } @Override public void pass_location_details(List<String> location) { frag = (PersonalInfoFragment) manager.findFragmentByTag("android:switcher:" + viewpager.getId() + ":" + 2); frag.get_post_location_details(location); Log.d("submitarea", location.get(0)); } @Override public void pass_post_details(List<String> post_details,ArrayList<CustomGallery> selected) { frag = (PersonalInfoFragment) manager.findFragmentByTag("android:switcher:" + viewpager.getId() + ":" + 2); frag.get_post_details(post_details,selected); Log.d("submitpostinfo","hello"+ post_details.get(5)); } } 

1er Fragmento (Aquí estoy tratando de pasar los datos usando la interfaz en onPause () ->

  package com.jbandroid.fragment; public class PostInfoFragment extends Fragment { private MenuItem myActionMenuItem; private Button myActionButton; private ActionBar actionBar; private String post_title, post_desc,post_status; private EditText submit_post_title, submit_post_desc; private Resources res; setPostInfo info; List<String> post_details; //RelativeLayout rel_submit_post_start_date,rel_submit_post_end_date; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View rootView = inflater.inflate(R.layout.fragment_post_info, container, false); /*if(!imageLoader.isInited()){*/ initImageLoader(); /*}*/ //handler = new Handler(); submit_post_title = (EditText) rootView .findViewById(R.id.submit_post_title); submit_post_desc = (EditText) rootView .findViewById(R.id.submit_post_description); actionBar = getActivity().getActionBar(); setHasOptionsMenu(true); post_details = new ArrayList<String>(); res = getResources(); setListeners(); Log.d("postinfo_oncreate view", "postinfo_oncreate view"); return rootView; } //interface to pass data to activity and then to PersonalInfoFragment public interface setPostInfo { //public void pass_post_details(List<String> post_details); public void pass_post_details(List<String> post_details,ArrayList<CustomGallery> selected); } //making sure if the parent activity has implemented interface @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 { info = (setPostInfo) activity; } catch (ClassCastException e) { throw new ClassCastException(activity.toString() + "must implemet setPostInfo"); } Log.d("postinfo_onattach", "postinfo_onattach"); } //passing form inputs to personalinfofragments @Override public void onPause() { super.onPause(); // setFormInputs(); passFormInputs(); ---> passing in onPause() This executes successfully Log.d("postinfo_onPAuse", "postinfo_onPause"); } //method to pass data to personalinfofragment private void passFormInputs() { try { post_title = submit_post_title.getText().toString(); post_desc = submit_post_desc.getText().toString(); post_status = "1"; if(post_title != null && post_title.length() > 0 && post_desc != null && post_desc.length() > 0 && post_status != null && post_status.length() > 0 ){ post_details.add(post_title); post_details.add(post_desc); post_details.add(post_status); info.pass_post_details(post_details,dataT); -->here I am passing values via }else{ activity to 3rd fragment Log.d("post_info", "values are null"); } } catch (Exception e) { e.printStackTrace(); } } //setting next button on actionbar public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { super.onCreateOptionsMenu(menu, inflater); // Inflate the menu items for use in the action bar inflater.inflate(R.menu.mymenu, menu); // Here we get the action view we defined myActionMenuItem = menu.findItem(R.id.my_action); View actionView = myActionMenuItem.getActionView(); // We then get the button view that is part of the action view if (actionView != null) { myActionButton = (Button) actionView.findViewById(R.id.action_btn); myActionButton.setText(R.string.txt_next); if (myActionButton != null) { // We set a listener that will be called when the return/enter // key is pressed myActionButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { actionBar.setSelectedNavigationItem(1); } }); } } } } 

Segundo Fragmento ->

  package com.jbandroid.fragment; public class LocationInfoFragment extends Fragment implements OnClickListener { private MenuItem myActionMenuItem; private Button myActionButton; private ActionBar actionBar; Dialog dialog; private EditText submit_post_exact_location; private TextView selected_country, selected_city, submit_post_exact_time; String country, city, exact_location, exact_time; setLocationInfo info; List<String> location; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View rootView = inflater.inflate(R.layout.fragment_location_info, container, false); actionBar = getActivity().getActionBar(); setHasOptionsMenu(true); submit_post_exact_location = (EditText) rootView .findViewById(R.id.submit_post_exact_location); submit_post_exact_time = (TextView) rootView .findViewById(R.id.submit_post_exact_time); selected_country = (TextView) rootView .findViewById(R.id.selected_country); selected_city = (TextView) rootView.findViewById(R.id.selected_city); location = new ArrayList<String>(); setListeners(); return rootView; } public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { super.onCreateOptionsMenu(menu, inflater); // Inflate the menu items for use in the action bar inflater.inflate(R.menu.mymenu, menu); // Here we get the action view we defined myActionMenuItem = menu.findItem(R.id.my_action); View actionView = myActionMenuItem.getActionView(); // We then get the button view that is part of the action view if (actionView != null) { myActionButton = (Button) actionView.findViewById(R.id.action_btn); myActionButton.setText(R.string.txt_next); if (myActionButton != null) { // We set a listener that will be called when the return/enter // key is pressed myActionButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { actionBar.setSelectedNavigationItem(2); } }); } } } public interface setLocationInfo { public void pass_location_details(List<String> location); } @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 { info = (setLocationInfo) activity; } catch (ClassCastException e) { throw new ClassCastException(activity.toString() + "must implement setLocationInfo"); } } @Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); //setLocationDetails(); } @Override public void onPause() { super.onPause(); setLocationDetails(); ----> doesnt executes since onPause isnt called when I navigate to 3rd fragment as it is an adjacent fragment of this fragment // Log.d("location : onPause", area); } private void setLocationDetails() { try { exact_location = submit_post_exact_location.getText().toString(); exact_time = submit_post_exact_time.getText().toString(); country = selected_country.getText().toString(); city = selected_city.getText().toString(); if (country != null && country.length() > 0 && !country.equalsIgnoreCase("select") && city != null && city.length() > 0 && !city.equalsIgnoreCase("select") && exact_location != null && exact_location.length() > 0 && exact_time != null && exact_time.length() > 0) { location.add(country); location.add(city); location.add(exact_location); location.add(exact_time); info.pass_location_details(location); } } catch (Exception e) { e.printStackTrace(); } } } 

En mi tercer fragmento estoy tratando de obtener estos valores

  public class PersonalInfoFragment extends Fragment { List<String> post_details; List<String> location; Button submit; public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View rootView = inflater.inflate(R.layout.fragment_personal_info, container, false); submit = (Button)rootView.findViewById(R.id.submitBtn); submit.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { //performing operations with the values obtained setPostItems(); insertintodb(); } }); return rootView; } public void get_post_details(List<String> post_details, ArrayList<CustomGallery> selected) { -->receiving values from this.post_details = post_details; 1st fragment this.selected = selected; Log.d("personalfrag(postinfo)", "hello" + post_details.get(5)); } //receiving values from 2nd fragment public void get_post_location_details(List<String> location) { this.location = location; Log.d("personalfrag(locationinfo)", "hello" + location.get(0)); } } 

Bueno, yo tenía el mismo problema para pasar los datos (no sólo la cadena) entre dos pestañas en un ViewPager. Así que aquí es lo que hice. I Utilice interfaces para comunicarse entre los diferentes componentes.

Los datos pasan de esta manera:

 Tab 1 -> Activity -> VewPageAdapter -> Tab 2 
  1. En la pestaña 1

Crear una interfaz.

 OnCartsDataListener mOncarOnCartsDataListener; public interface OnCartsDataListener { public void onCartsDataReceived(ArrayList<CartsViewModel> cartsViewModels); } @Override public void onAttach(Activity activity) { super.onAttach(activity); try { mOncarOnCartsDataListener = (OnCartsDataListener)activity; }catch (ClassCastException e){ } } // now call mOncarOnCartsDataListener.onCartsDataReceived(data) when you have the data 
  1. En Actividad

Implementar la interfaz y anular el método

 ViewPagerAdapter adapter; adapter = new ViewPagerAdapter(getSupportFragmentManager(), Titles, Numboftabs); @Override public void onCartsDataReceived(ArrayList<CartsViewModel> cartsViewModels) { Log.d(TAG, "data received to Activity... send to view pager"); adapter.onCartsDataReceived(cartsViewModels); } 

3. EN ViewPagerAdapter

También implementa la interfaz y anula el método

 @Override public void onCartsDataReceived(ArrayList<CartsViewModel> cartsViewModels) { Log.d(TAG, "data received to view pager... sending to tab 2"); if(tab2!=null){ tab2.onCartsDataReceived(cartsViewModels); }else{ Log.d(TAG, "tab2 is null"); } } 
  1. Finalmente tab 2

También implementa la interfaz y anula el método

 @Override public void onCartsDataReceived(ArrayList<CartsViewModel> cartsViewModels) { Log.d(TAG, "Finally ! received data to tab 2"); if(cartsViewModels!=null){ for(CartsViewModel cart : cartsViewModels){ Log.d(TAG,"got it :"+cart.getCartName()); } } } 

¿Puedes hacer algo como esto? Primero cree cualquier estructura de datos como Arraylist en su actividad principal. A continuación, envíe una referencia de ese modelo de datos a sus fragmentos. Ahora actualice esos datos cuando, al cambiar sus campos de texto. Al hacer esto todo el fragmento puede ver los valores actualizados. Así que los fragmentos pueden actualizar estos datos en sí y no tenemos que enviar esos datos ya que ya está compartido. Te lo explicaré con tu ejemplo. Trate de mejorar esto. Puede mantener el modelo de datos específicos de fragmentos, a continuación, cada fragmento puede acceder a los datos con el conocimiento de ese propietario de datos.

TabsPagerAdapter.java

 public class TabsPagerAdapter extends FragmentPagerAdapter { public TabsPagerAdapter(FragmentManager fm,SubmitPostActivity activity){ super(fm); } @Override public Fragment getItem(int index) { switch(index) { case 0 : //PostInfoFragment return new PostInfoFragment(0,activity); case 1 : //LocationInfoFragment return new LocationInfoFragment(1,activity); case 2 : //PersonalInfoFragment return new PersonalInfoFragment(2,activity); } return null; } @Override public int getCount() { return 3; } } 

ViewPagerActivity ->

 package com.jbandroid; public class SubmitPostActivity extends FragmentActivity implements ActionBar.TabListener,LocationInfoFragment.setLocationInfo{ private ViewPager viewpager; private ActionBar actionBar; private TabsPagerAdapter mAdapter; FragmentManager manager; PersonalInfoFragment frag; List<String> location; /*private MenuItem myActionMenuItem; private Button myActionButton;*/ //Tab titles private String[] tabs = {"Post Info" , "Location Info" , "Personal Info" }; public List<String> dataModel = new ArrayList<String>(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.action_submit_post); viewpager = (ViewPager) findViewById(R.id.pager); actionBar = getActionBar(); manager = getSupportFragmentManager(); mAdapter = new TabsPagerAdapter(getSupportFragmentManager(),this); //viewpager.setOffscreenPageLimit(2); viewpager.setAdapter(mAdapter); //actionBar.setHomeButtonEnabled(false); actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS); for (String tab : tabs){ actionBar.addTab(actionBar.newTab().setText(tab).setTabListener(this)); } if(savedInstanceState != null){ actionBar.setSelectedNavigationItem( savedInstanceState.getInt("tab",0)); } } } 

1er Fragmento =>

 public class PostInfoFragment extends Fragment { private MenuItem myActionMenuItem; private Button myActionButton; private ActionBar actionBar; private String post_title, post_desc,post_status; private EditText submit_post_title, submit_post_desc; private int position; private Resources res; SubmitPostActivity callingActivity; List<String> post_details; public PostInfoFragment(int position,SubmitPostActivity callingActivity ) { this.callingActivity = callingActivity; this.position = position; } //RelativeLayout rel_submit_post_start_date,rel_submit_post_end_date; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View rootView = inflater.inflate(R.layout.fragment_post_info, container, false); /*if(!imageLoader.isInited()){*/ initImageLoader(); /*}*/ //handler = new Handler(); submit_post_title = (EditText) rootView .findViewById(R.id.submit_post_title); submit_post_desc = (EditText) rootView .findViewById(R.id.submit_post_description); actionBar = getActivity().getActionBar(); setHasOptionsMenu(true); post_details = new ArrayList<String>(); res = getResources(); setListeners(); Log.d("postinfo_oncreate view", "postinfo_oncreate view"); //this is editText onchange listner do the same for submit_post_desc as well submit_post_title.addTextChangedListener( new TextWatcher() { @Override public void onTextChanged( CharSequence s, int start, int before, int count ) { } @Override public void beforeTextChanged( CharSequence s, int start, int count, int after ) { } @Override public void afterTextChanged( Editable s ) { if( callingActivity != null ) { //use this.position in order to update relevant data List<String> post_details = callingActivity.dataModel; if( post_details == null ) { post_details = new ArrayList<String>(); } post_details.add(s.toString()); } } } ); return rootView; } //making sure if the parent activity has implemented interface @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 { callingActivity = (SubmitPostActivity) activity; } catch (ClassCastException e) { throw new ClassCastException(activity.toString() + "must implemet setPostInfo"); } Log.d("postinfo_onattach", "postinfo_onattach"); } } 

Por favor, no que esto no puede compilar como es. Trate de obtener el concepto.

  • ¿Cómo evitar que una vista de desplazamiento se desplace a una vista web después de cargar los datos?
  • Vista de desplazamiento horizontal en páginas de desplazamiento horizontal
  • Android Poner la animación en la página de desplazamiento en la vista paginador utilizando fragmento
  • ViewPager + FragmentPagerAdapter dentro de un DialogFragment obtiene "IllegalArgumentException: No se encontró ninguna vista ..."
  • No se puede actualizar fragmentos de texto al cambiar las tarjetas
  • No se puede cerrar NavigationDrawer con desplazamiento de derecha a izquierda
  • Android Viewpager como Galería de imágenes de diapositivas
  • Cambiar color TabSelector en v4 ViewPager
  • ¿Cómo puedo usar View pager con touchimageview?
  • Toque los Listeners para las vistas de padres y niños
  • Resaltar o subrayar seleccionado TabPageIndicator
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.