I need to pass some variable from activity to fragment inside a tab layout. I found there are 2 preferred ways of passing argument bundles to the fragment by its initialization methods for the tab layout.
By creating static newInstance() method and providing details.
Creating instance of fragment inside FragmentPagerAdapter
But, I have some doubts how this works.
If I create this this is:
public class SectionsPagerAdapter extends FragmentPagerAdapter {
MyFragment myFragment;
public SectionsPagerAdapter(FragmentManager fm) {
super(fm);
myFragment = new MyFragment();
Bundle args = new Bundle();
args.putString("id", id);
myFragment.setArguments(args);
}
// ...
}
Here I am creating the instance of fragment and setting its argument afterwords.
And if I create it in newInstance() method something like this:
public static MyFragment newInstance(String id) {
MyFragment myFragment = new MyFragment();
Bundle args = new Bundle();
args.putString("id", id);
myFragment.setArguments(args);
return myFragment;
}
Some doubts:
When will the onCreate() or onCreateView() will be called? What if after line new MyFragment() and before setting bundle?
Is there any possibility where getArguments can return null?
In both ways I am doing the same thing. Setting args after new MyFragment() call. How late I can set the arguemnts. Is it necessary to set arguments exactly after the new MyFragment() call?
Sorry, if I asked some silly question. But I am new to Fragments. Thanks :)
onCreate() and onCreateView() will be called sometime after you've committed the fragment transaction. i.e. called commit(). And you set bundle before that.
As long as you're setting bundle before commit, getArguments shouldn't be null.
Both are doing the same thing. In 1st you're creating the fragment instance by yourself and setting bundle yourself. In 2nd you're using what is called a factory method (Effective Java Item 2) which is managed by your fragment. So it's difficult to make mistake in 2nd as arguments are always set.
Related
I have a ViewPager which holds Fragments. ViewPager has an adapter of FragmentStatePagerAdapter
Adapter's getItem method.
#Override
public Fragment getItem(int position) {
String text= dbHelper.getText(position);
CustomFragment frg = new CustomFragment(text);
return frg;
}
I am initializing the fragment in the getItem method of the adapter.
Everything works perfectly.
When the orientation changes however, instead of restoring my initialized fragments, CustomFragments are created using the default constructor of CustomFragment. So this creates fragments with dummy data.
What is the reason of this?
How can i restore the previously created fragments?
The ideal way to initialise your Fragments is to create a factory method like:
public static CustomFragment newInstance(String text) {
Bundle arguments = new Bundle();
arguments.put("someText", text);
CustomFragment fragment = new CustomFragment();
fragment.setArguments(arguments);
return fragment;
}
and get the arguments with getArguments() in the onCreate() method and process it to initialise whatever you want in the fragment.
This way when your fragments are recreated on configuration change, the arguments are persisted and the Fragments take care of themselves when their onCreate() method is called.
You might have noticed the lint warnings about the same if you are using the latest tools.
In android programming,
When we add fragment to specific layout,
we can use following code snippet
Fragment fragment = new SampleFragment();
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.content_layout, fragment);
fragmentTransaction.commit();
or
Fragment fragment = SampleFragment.getInstance();
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.content_layout, fragment);
fragmentTransaction.commit();
I cannot understand what is difference between that fragment object define sentence.
From some sources, when use 'Fragment.getInstance()' like singleton pattern, pass bundle data to fragment with 'getInstance(Bundle data)' method parameter.
Could you tell me what difference?
getInstance() for Fragment instantiation is a familiar design pattern, which encapsulate the creation of the fragment and its arguments. It means basically that the Fragment is responsible on creating its own instance and should be cleaner and safer than calling only new Fragment(), since you can pass additional data/bundle and "force" the user to use this method. Notice that you are still calling new Fragment() in the getInstance() method, it does not replace it.
public static SomeFragment newInstance(int a, boolean b) {
SomeFragment someFragment = new SomeFragment();
Bundle args = new Bundle();
args.putInt("a", a);
args.putBoolean("b",b);
.....
someFragment.setArguments(args);
return someFragment;
}
that way you will have only one place you would create the parameters bundle and not every time you want to instantiate the fragment.
First thing to note is that if the system destroyed your fragment and has to re-create it, it will call the constructor with no-args. This thing implies that you have to save your arguments somewhere to be used later (You can't create a constructor with args).
Now, let's get back to your question. For the moment, the 2 blocks of code are almost identical, but only for the example you provided. If you should pass some params to your fragment, things are a little different. The getInstance should add the needed arguments to your fragment, guaranteeing that they will be available in a future moment.
Personally, I use the getInstance/newInstance (you may find variation of it, right now, creating a template fragment in Android Studio use the newInstance) method passing the parameters that I need in that fragment. For example, if I need two strings in that fragment, I will pass them to getInstance method
and save them in the fragment arguments to make sure that they will be available if the fragment is re-created.
public static MyFragment getInstance(String param1, String param2) {
MyFragment fragment = new MyFragment();
Bundle args = new Bundle();
args.putString(KEY_ONE, param1);
args.putString(KET_TWO, param2);
fragment.setArguments(args);
return fragment;
}
Of course, for this method you can pass a Bundle, but I think that is a little bit clearer in this way, specifying each parameter the fragment will use.
That being said, if you want to create an equivalent of the above block you should use something like this:
MyFragment fragment = new MyFragment();
Bundle args = new Bundle();
// set your arguments here
fragment.setArguments(args);
// and from here use your code as you did
To conclude, using getInstance is used to stop the code repetition (note that if you should create the fragment 10 times, you should copy the above code 10 times) and, if you create the fragment correctly (second block of code) you don't really have to use the getInstance method, but it's recommended.
I want to create same fragment multiple times in view pager with different arguments how can i do it?
Now i have a static single argument constructor in a fragment which i call to initialize the fragment
Is there a simple way to do this.
You could use setArguments() method, for each of your Fragment. Do something like this:
Fragment myFragment = new Fragment();
Bundle data = new Bundle();
data.putString("data_1","Hello");
myFragment.setArguments(data);
Then in your Fragment, do this:
Bundle data = getArguments();
String data_1 = data.getString("data_1");
I have an activity that calls to a web service and I want to pass these result to a fragment. Obviously the web service is invoked by an AsyncTask, so the fragment is loaded before getting result.
How can I pass this paramteter from activity's AsyncTask to fragment when is received?
You can implement a method inside your Fragment and call it when needed. For bidirectional communication between an Activity and a Fragment see http://developer.android.com/training/basics/fragments/communicating.html
Set bundle in your fragment.
Bundle args = new Bundle();
args.putInt("id",value);
Fragment newFragment = new Fragment();
newFragment.setArguments(args);
In your fragment get the bundle as
Bundle b = getArguments();
String s = b.getInt("id");
You could move the AsyncTask into the fragment.
But if you wish to keep your current set up, you should save the Fragment reference when you initialize it, and create a public function in the fragment that takes the new data as a parameter.
So the activity code could look like this:
MyFragment fragment = new MyFragment();
getFragmentManager().beginTransaction().replace(android.R.id.content, fragment).commit();
and then you could call:
fragment.updateData(myNewData);
Just make sure to do the appropriate null-checks, just to be safe.
I currently have this Custom ArrayList:
ArrayList<PlaceDetails> place_list = new ArrayList<PlaceDetails>();
which will be populated during the onCreateView() portion.
I am unsure as of how do I pass this ArrayList in a bundle from this fragment class to another fragment class. Below is the snippet of my codes:
public void Map(View view){
if(hasConnection() == true){
Bundle b = new Bundle();
// how should I be passing the ArrayList in this bundle?
FragmentTransaction ft = getSherlockActivity().getSupportFragmentManager().beginTransaction();
TOnlineMapViewFragment mapfrag = TOnlineMapViewFragment.newInstance(b);
ft.replace(R.id.container, mapfrag).addToBackStack(null).commit();
}
}
So I've created the bundle and I wanted to pass it to the next fragment with the newInstance() method. How should I do this?
Consider implementing Parcelable interface in your classes. Then you would be able to store PlaceDetails in Bundle and pass it to setArguments() method.
I've found a tutorial: http://shri.blog.kraya.co.uk/2010/04/26/android-parcel-data-to-pass-between-activities-using-parcelable-classes/
I haven't testes it but it looks good.
Are you really sure a bundle is really needed?
TOnlineMapViewFragment mapfrag = TOnlineMapViewFragment.newInstance(b);
mapfrag.setPlaceList(place_list)
Should be trivial to create setPlaceList(ArrayList<PlaceDetails> place_list) ...