json leader
json leader

Reputation: 153

How to pass data between fragment in viewpager?

There is a tabLayout and ViewPager. So I want to pass data from fragment1 to fragment2.

NOTE: fragment1 vs fragment2 lies in VIewPager. So I can't pass data follow normal ways.

FragmentTransaction fragmentTx=this.FragmentManager.BeginTransaction();
            TracksByGenres fragTrack=new TracksByGenres();
            fragTrack.AddData(items[e.Position]);
            //get our item from listview

            fragmentTx.Replace(Resource.Id.fragmentContainer,fragTrack);    
            fragmentTx.AddToBackStack(null);
            fragmentTx.Commit();

Upvotes: 5

Views: 17163

Answers (6)

Hitesh Sahu
Hitesh Sahu

Reputation: 45052

This is an old question and all above answers are valid.This is 2019 and Android have changed a lot since Android Architecture Components

enter image description here

If you are using Android JetPack than you can add an Observer on a Live Data in your Host Activity class and listen for changes in Fragment class

Create a Singleton repo to hold live data

/**
 * Data Class Live Data
 */
class Repository private constructor() {


    private var currentProgress: MutableLiveData<Float> = MutableLiveData()

    fun getLiveProgress(): MutableLiveData<Float> {
        return currentProgress
    }

    companion object {

        private val mInstance: Repository =
                Repository()

        @Synchronized
        fun getInstance(): Repository {
            return mInstance
        }
    }
}

Set Live data anywhere from Activity or Fragment class class

  viewPager.addOnPageChangeListener(object : ViewPager.OnPageChangeListener {
            override fun onPageScrollStateChanged(state: Int) {
            }

            override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {
                headMotionScene.progress = positionOffset
                Repository.getInstance().getLiveProgress().value = positionOffset
            }

            override fun onPageSelected(position: Int) {
            }

        })

Observe change in data from your Fragment/ Service class

    Repository.getInstance().getLiveProgress().observe(this, Observer<Float> {
        motionLayout.progress = it
    })

Upvotes: 5

Manish Singh Rana
Manish Singh Rana

Reputation: 872

The best way would be using SharedPreferences

For this, we need to define and initialize SharedPreferences like this

SharedPreferences preferences;
public static final String MY_SHARED_PREFERENCES = "MySharedPrefs" ;
preferences = getSharedPreferences(MY_SHARED_PREFERENCES, Context.MODE_PRIVATE);

To save value, use below code.

SharedPreferences.Editor editor = preferences.edit();
editor.putString("YOUR_TAG_NAME", "value");
editor.commit();

To retrieve data from SharedPreferences in Second fragment, use below code

public static final String MY_SHARED_PREFERENCES = "MySharedPrefs" ;
SharedPreferences myPreferences = getSharedPreferences(MY_SHARED_PREFERENCES , MODE_PRIVATE); 
String restoredText = myPreferences.getString("YOUR_TAG_NAME", null);

OR

You can also use the below way to pass data between fragments, but this one is a bit tedious and will be helpful in case you have the bulk data which demand the transfer to another fragment inside viewpager.

To pass data from 1st Fragment() (assume it as FirstFragment) to 2nd Fragment (assume it as SecondFragment) inside Viewpager, follow below steps.

Step 1: Make an interface with a method signature like below.

public interface ShareIt {
    public void passIt(String data);
}

Step 2: SecondFragment needs to implement ShareIt interface and should Override the passIt method and you need to store data in local variable which is being passed from FirstFragment. Apart from this I am passing instance of Viewpager and index of Fragment. Instance of Viewpager is required as a parameter for findFragmentByTag method. So your SecondFragment would look like this.

public class SecondFragment extends Fragment implements ShareIt {

private NonSwipeableViewPager pager;
private int index;
private String string;

public static SecondFragment newInstance(int index, NonSwipeableViewPager viewPager) {
    SecondFragment f = new SecondFragment();
    Bundle args = new Bundle();
    args.putSerializable("VP", viewPager);
    args.putInt("index", index);
    f.setArguments(args);
    return f;
}


@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
    View rootView = inflater.inflate(R.layout.fragment_second, container, false);

    Bundle bundle = getArguments();
    pager = (NonSwipeableViewPager) bundle.getSerializable("VP");
    index = bundle.getInt("index");



    return rootView;
}

@Override
public void passIt(String data) {
    string = data; // Storing the data which is been passed from FirstFargment in a local variable
    Toast.makeText(getActivity(), "" + data, Toast.LENGTH_SHORT).show();
 }
}

Step 3: Now from FirstFragment we need to locate SecondFragment inside Viewpager like this

Fragment frag = getActivity().getSupportFragmentManager().findFragmentByTag("android:switcher:" + R.id.pager + ":" + pager.getCurrentItem()); 
// pager.getCurrentItem() will give 0, index 0 will have instance of FirstFragment, but we want instance of SecondFragment, so we need to pass 1 instead of pager.getCurrentItem()
Fragment frag = getActivity().getSupportFragmentManager().findFragmentByTag("android:switcher:" + R.id.pager + ":" + 1); 

As we have got instace of SecondFragment, we can call passIt method of SecondFragment to pass the data like this

((SecondFragment)dataBoy).passIt("Hello..!!!!");

So your FirstFragment will look something like this.

public class FirstFragment extends Fragment {

private Button btnNext;

private NonSwipeableViewPager pager;
private int index;




public static FirstFragment newInstance(int index, NonSwipeableViewPager viewPager) {
    FirstFragment f = new FirstFragment();
    Bundle args = new Bundle();
    args.putSerializable("VP", viewPager);
    args.putInt("index", index);
    f.setArguments(args);
    return f;
}


@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
    View rootView = inflater.inflate(R.layout.fragment_first, container, false);
    Bundle bundle = getArguments();
    pager = (NonSwipeableViewPager) bundle.getSerializable("VP");
    index = bundle.getInt("index");
    btnNext = findViewById(R.id.btnNext);
    Fragment frag= getActivity().getSupportFragmentManager().findFragmentByTag("android:switcher:" + R.id.pager + ":" + 1);




    btnNext.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {

            ((SecondFragment)frag).passIt("Hello..!!!!");           

        }
    });


    return rootView;
  }

}

Upvotes: 2

Zain
Zain

Reputation: 2372

Depends on the nature of the data.

Ideally the data is held in the Activity or ViewPager Adapter- so when each Fragment is built it gets its data from the Activity etc. See this question on SO

The best solution in my opinion is, if you can store the data in a DataBase, the each Fragment store the data inside the database via the CotnentProvider then you could use Loaders specifically CursorLoaderto retrieve the data - this approach will always provide you with the latest data as the Laoder will be notified when it changes.

Take a look at the official docs here for an example

I would not recommend using Preferences as suggested above to store complex data other than primitives etc for settings.

Upvotes: 0

Vishwesh Jainkuniya
Vishwesh Jainkuniya

Reputation: 2839

Use sharedPreferences

SharedPreferences sharedpreferences;
public static final String MyPREFERENCES = "MyPrefs" ;
sharedpreferences = getSharedPreferences(MyPREFERENCES, Context.MODE_PRIVATE);

Save value

SharedPreferences.Editor editor = sharedpreferences.edit();
editor.putString("TAG_NAME", "value");
editor.commit();

Retrieve data from preference: In Second fragment

public static final String MyPREFERENCES = "MyPrefs" ;
SharedPreferences prefs = getSharedPreferences(MyPREFERENCES , MODE_PRIVATE); 
String restoredText = prefs.getString("TAG_NAME", null);

Upvotes: 7

dindinii
dindinii

Reputation: 655

Try the below code pass data between fragments

Bundle bundle = new Bundle();
FragmentTransaction fragmentTx=this.FragmentManager.BeginTransaction();
TracksByGenres fragTrack=new TracksByGenres();
bundle.putString(key, value); i.e bundle.putString("myKey",items[e.Position]);
fragTrack.setArguments(bundle);
                //get our item from listview
fragmentTx.Replace(Resource.Id.fragmentContainer,fragTrack);    
fragmentTx.AddToBackStack(null);
fragmentTx.Commit();

retrieve the data from called fragment onCreate() by

Bundle bundle = this.getArguments();
String value= bundle.putString(key, defaultValue); i.e bundle.putString(myKey, "");

Upvotes: 0

Joopkins
Joopkins

Reputation: 1644

You can use an interface.

public interface DataBoy{
    public void bigDog(Data data);
}

inside fragment 1:

DataBoy dataBoy = (DataBoy)getActivity().getSupportFragmentManager().findFragmentById(R.id.fragment2);

dataBoy.bigDog(data);

inside fragment 2:

fragment2 implements DataBoy {
...

@Override
public void bigDog(Data data);
doSomethingWith(data);
}

Upvotes: 4

Related Questions