Comunicación entre fragmentos en ViewPager

Estoy intentando hacer esto: http://android-er.blogspot.com/2012/06/communication-between-fragments-in.html Excepto que estoy usando un FragmentStatePagerAdapter

Tengo una actividad con dos fragmentos ( FragmentA & FragmentB )

FragmentA tiene un texto de edición y un botón, FragmentB tiene una vista de texto

Ahora todo lo que quiero es que cada vez que ingrese algo en el texto de edición y haga clic en el botón, ese algo aparezca en mi vista de texto.

Actividad principal:

public class MainActivity extends FragmentActivity { ViewPager viewPager = null; String TabFragmentB; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); viewPager = (ViewPager)findViewById(R.id.pager); FragmentManager fragmentManager = getSupportFragmentManager(); viewPager.setAdapter(new MyAdapter(fragmentManager)); } public class MyAdapter extends FragmentStatePagerAdapter { public MyAdapter (FragmentManager fm) { super(fm); } @Override public Fragment getItem(int i) { Fragment fragment = null; if (i == 0) { fragment = new FragmentA(); } if (i == 1) { fragment = new FragmentB(); } return fragment; } @Override public int getCount() { return 2; } } public void setTabFragmentB(String t) { TabFragmentB = t; } public String getTabFragmentB() { return TabFragmentB; } } 

Fragmento A:

 public class FragmentA extends Fragment { EditText et; Button bt; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View v = inflater.inflate(R.layout.fraga, container, false); et = (EditText)v.findViewById(R.id.edit1); bt = (Button)v.findViewById(R.id.button1); bt.setOnClickListener(Click); return v; } OnClickListener Click = new OnClickListener(){ @Override public void onClick(View v) { String textPassToB = et.getText().toString(); String TabOfFragmentB = ((MainActivity)getActivity()).getTabFragmentB(); FragmentB fragmentB = (FragmentB)getActivity() .getSupportFragmentManager() .findFragmentByTag(TabOfFragmentB); fragmentB.updateText(textPassToB); } }; } 

FragmentB:

 public class FragmentB extends Fragment { TextView tv; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View v = inflater.inflate(R.layout.fragb, container, false); tv = (TextView)v.findViewById(R.id.text1); String myTag = getTag(); ((MainActivity)getActivity()).setTabFragmentB(myTag); return v; } public void updateText(String t){ tv.setText(t); } } 

LogCat:

 FATAL EXCEPTION: main java.lang.NullPointerException at lmf.sample1.FragmentA$1.onClick(FragmentA.java:43) at android.view.View.performClick(View.java:4212) at android.view.View$PerformClick.run(View.java:17476) at android.os.Handler.handleCallback(Handler.java:800) at android.os.Handler.dispatchMessage(Handler.java:100) at android.os.Looper.loop(Looper.java:194) at android.app.ActivityThread.main(ActivityThread.java:5371) at java.lang.reflect.Method.invokeNative(Native Method) at java.lang.reflect.Method.invoke(Method.java:525) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:833) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:600) at dalvik.system.NativeStart.main(Native Method) 

Cada vez que hago clic en el botón de mi primer fragmento, mi aplicación falla. ¿Qué diablos es el problema?

    1. Podría usar Intents (registrar receptor de difusión en el fragmento B y enviar transmisiones desde el fragmento A.
    2. Use EventBus: https://github.com/greenrobot/EventBus . Es mi enfoque favorito. Muy conveniente de usar, comunicaciones fáciles entre cualquier componente (actividad y servicios, por ejemplo).

    Pasos para hacer:

    Primero, crea una clase para representar el evento cuando tu texto cambie:

     public class TextChangedEvent { public String newText; public TextChangedEvent(String newText) { this.newText = newText; } } 

    Luego, en el fragmento A:

     //when text changes EventBus bus = EventBus.getDefault(); bus.post(new TextChangedEvent(newText)); 

    en el fragmento B:

     EventBus bus = EventBus.getDefault(); //Register to EventBus @Override public void onCreate(SavedInstanceState savedState) { bus.register(this); } //catch Event from fragment A public void onEvent(TextChangedEvent event) { yourTextView.setText(event.newText); } 

    Los fragmentos tienen acceso a su Actividad principal.
    Por lo tanto, el enfoque más simple es registrar una callback en la Actividad principal.

    Actualización: Enviar caché agregado a MainActivity.

      public class MainActivity extends FragmentActivity { private OnButtonClicked mOnButtonClicked; private String mSubmitCache; public interface OnButtonClicked { void submit(final String s); } public void setOnButtonClicked(final OnButtonClicked c) { mOnButtonClicked = c; // deliver cached string, if any if (TextUtils.isEmpty(mSubmitCache) == false) { c.submit(mSubmitCache); } } public void buttonClicked(final String s) { if (mOnButtonClicked == null) { // if FragmentB doesn't exist jet, cache value mSubmitCache = s; return; } mOnButtonClicked.submit(s); } } public class FragmentA extends Fragment implements OnClickListener { private MainActivity mMain; private Button mButton; @Override public onAttach(Activity a) { mMain = (MainActivity) a; } @Override public void onClick(View v) { mMain.buttonClicked("send this to FragmentB."); } } public class FragmentB extends Fragment implements MainActivity.OnButtonClicked { private MainActivity mMain; private TextView mTextView; // Called when the fragment's activity has been created // and this fragment's view hierarchy instantiated @Override public void onActivityCreated(Bundle savedState) { mMain = (MainActivity) getActivity(); mMain.setOnButtonClicked(this); } @Override void submit(final String s) { mTextView.setText(s); } } 

    FragmentB ni siquiera se crea hasta que cambies a él tan fragmentB.updateText(textPassToB); te da NullPointerException.

    Necesitará almacenar el texto de EditText en su actividad y más adelante cuando (si) se cree el FragmentB necesitará leer el valor de él.

    Yo uso la solución del Sr. Rodion arriba. Pero, además, Android Studio me pidió que añadiera la anotación onEvent antes del método onEvent .

    Me gusta esto:

     @Subscribe public void onEvent(TextChangedEvent event) { textView.setText(event.newText); } 

    De acuerdo con la API de EventBus :

    Los suscriptores implementan métodos de manejo de eventos (también llamados “métodos de suscriptor”) que serán llamados cuando se publique un evento. Estos se definen con la anotación @Subscribe. Tenga en cuenta que con EventBus 3 el nombre del método se puede elegir libremente (no hay convenciones de nomenclatura como en EventBus 2).