Search code examples
androidandroid-fragmentsandroid-viewpagerandroid-button

How to Synchronize Data Between Viewpager Fragments


With the following code I can click a button to send a string from one fragment (Fragment A) into a MainActivity. How would I retrieve the string from the MainActivity and display it on a fragment B all in one go? I would like the fragments to act synchronized; to have Fragment B update itself as soon as I click the button in Fragment A. I can't seem to find anything in SO on this.

Interface:

public interface OnDataListener {
    public void onDataReceived(String data);
}

Fragment A data listener:

OnDataListener mOnDataListener;

@Override
public void onAttach(Context context) {
    try{
        mOnDataListener = (OnDataListener) context;
        Log.d(TAG, "onAttach was called" + context);
    }catch (ClassCastException e){
        Log.e(TAG, "onAttach: ClassCastException: " + e.getMessage() );
    }
    super.onAttach(context);
}

Button logic in Fragment A's onCreateView:

button.setOnClickListener(new View.OnClickListener() {
        public void onClick(View v) {

          String newTextString = editTextView.getText().toString();
          mOnDataListener.onDataReceived(newTextString);

        }
      });

MainActivity data receiver

public class MainActivity extends AppCompatActivity implements OnDataListener {


@Override
public void onDataReceived(String data) {

    Log.e(TAG, "MainActivity received this string " + data );

            }
}

Solution

  • Solution 1: Using Callbacks

    //this will work if your fragment instance is active so check viewpager offscreenpage limit

    (You can also use solution 3 mentioned by Farid Haq, which do the same by doing work of activity itself)

    Here, Activity implements callback OnDataUpdateListener

    interface OnDataUpdateListener{
        void passDataToFragmentB(String data)
    }
    

    Activity code:

    Fragment instanceFragmentB;
    // intialise it somewhere in your activity
    // or get from viewpager adapter
    
    @Override
    void passDataToFragmentB(String data){
        instanceFragmentB.onDataChange(data)
    }
    

    Fragment A code:

    OnDataUpdateListener mOnDataUpdateListener;
    onAttach(Activity activity){
        mOnDataUpdateListener=  (OnDataUpdateListener) activity
    }
    
    onViewCreated(){
        somebutton.onClick{
            mOnDataUpdateListener.passDataToFragmentB("someString")
        }
    }
    

    Fragment B code:

    onDataChange(String data){
        //do your work with update data passed from fragment A  
    }
    

    Solution 2: Using EventBus or RxBus

    //this will work if your fragment instance is active so check viewpager offscreenpage limit

    Using event or rxbus, post new updated value on bus and make destination fragment observing that same value type.

    Fragment A:

    onViewCreated(){
        somebutton.onClick{
            EventBus.post("your data")
        }
    }
    

    Fragment B:

    @Subsribe
    void onDataChange(String data){
        //do your work with update data passed from fragment A  
    }
    

    Solution 3: Using ViewModel.

    Take viewmodel with context of activity in all fragment and Wrap String with LiveData.

    Whenever, string data is changed, just post new data on String Livedata object. All fragment observing that livedata will get updated value.