Reputation: 153
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
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
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
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
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 CursorLoader
to 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
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
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
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