I wrote a custom static method to create my fragment. Fragment is a subclass of android.support.v4.app.Fragment class.
Method to create my fragment is bellow.
public static AddItemFragment newInstance(UUID listId, UUID itemId){
AddItemFragment fragment=new AddItemFragment();
Bundle bundle=new Bundle();
bundle.putSerializable(EXTRA_DATA_LIST_ID,listId);
bundle.putSerializable(EXTRA_DATA_ITEM_ID, itemId);
fragment.setArguments(bundle);
return fragment;
}
In my onCreate method, I am attempting to read data from bundle.
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mListId = (getArguments().getSerializable(EXTRA_DATA_LIST_ID) == null ? null : (UUID) getArguments().getSerializable(EXTRA_DATA_LIST_ID));
mItemId = (getArguments().getSerializable(EXTRA_DATA_ITEM_ID) == null ? null : (UUID) getArguments().getSerializable(EXTRA_DATA_ITEM_ID));
}
Well the problem is that getArguments() method never returns bundle. It always returns NULL. I don't understand why. savedInstanceState is NULL as well.
Silly me was overriding bundle set in the Fragment with Activity's savedInstanceState bundle which at that point is NULL.
DUH...
Related
Hi I'm learning now about Fragments and I have some doubts.
V1:
So the correct way to create a new Fragment should be with "newInstance" instead of a constructor and would be something like this:
Fragment fragment = MyFragment.newInstance(variable);
And the code on the class "MyFragment" should be this:
private static final String ARG_PARAM1 = "param1";
private int variable;
public MyFragment() {
//Empty constructor
}
New instance will receive the param and will put them on a Bundle and set the argument for the class
public static mi_fragment newInstance(Int param1) {
MyFragment fragment = new MyFragment();
Bundle args = new Bundle();
args.putInt(ARG_PARAM1, param1);
fragment.setArguments(args);
return fragment;
}
Then after setting it the method onCreate will pick up the argument:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
variable = getArguments().getInt(ARG_PARAM1);
}
V2:
But I still can't see the problem with using the constructor and setting the arguments programatically:
Bundle bundle = new Bundle();
bundle.putInt("key", variable);
Fragment fragment = new MyFragment();
fragment.setArguments(bundle);
Then I pick up the argument on the method onCreate:
public void onCreate(#Nullable Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
Bundle bundle = this.getArguments();
if(bundle!=null){
variable = getArguments().getInt("key");
}
}
So I decided to search on the internet about this and I found a good answer but I still can't seem to understand it or when you could use it.
the way to pass stuff to your Fragment so that they are available after a Fragment is recreated by Android is to pass a bundle to the setArguments method.
This Bundle will be available even if the Fragment is somehow recreated by Android.
So my conclusion is that you keep the bundle alive and using the newInstance could make you return to the last fragment for example. But probably I'm wrong so I need help.
Question: What's the main difference between both and how do you benefit from newInstance ? An example.
I am trying to get bundle extras from activity 1 to fragment of activity 2 but getargument() always returns as null.
//Using this to get string in fragment
String value = getArguments().getString("abc");
//activity1 code that i used to get the extras
Bundle bundle = new Bundle();
bundle.putString("abc", townextra);
UserFragment myFrag = new UserFragment();
myFrag.setArguments(bundle);
There is a problem with logic of passing data.
Correct way would be: Pass data from Activity1 to Activity2, and then from Activity2 to Fragment.
all fixed. I added a new function on my activity 2 to create fragment. instead of doing it in oncreat. it all works fine, thanks
Your Activity
Bundle bundle = new Bundle();
bundle.putString("params", "Your String data");
// set MyFragment Arguments
MyFragment myObj = new MyFragment();
myObj.setArguments(bundle);
The Fragment.
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
mParam = getArguments().getString("params");
}
}
But will be better if you show the code how you pass data between activities and then use my answer.
And please add your fragment code.
Im developing a small android application, i was using shared preference in order to transfer data between fragments. now i want to use bundle but the problem is the bundle in the second fragment getting null value how do i solve that problem ?
here are some part of code
... some usefull Code in first fragment
args.putLong("favoriteCountry", countryListSpinnerData.get(favoriteCountrySpinner.getSelectedItemPosition()).getId());
args.putInt("favoriteCurrency", currencySpinner.getSelectedItemPosition());
args.putDouble("favoriteBudget", Double.parseDouble(budgetEditText.getText().toString()));
args.putString("additionalInformation", additionalInformationEditText.getText().toString());
MoneyPartnerShipStepTwo moneyPartnerShipStepTwo = new MoneyPartnerShipStepTwo();
moneyPartnerShipStepTwo.setArguments(args);
FragmentHelper.NAVIGATE_FRAGMENT(new MoneyPartnerShipStepTwo(), getActivity())
Now the second fragment
#Override
public void onCreate(Bundle savedInstanceState) { // savedInstanceState is null why ???
super.onCreate(savedInstanceState);
if (getArguments() != null) {
this.bundle = savedInstanceState;
}
setHasOptionsMenu(true);
}
you create new MoneyPartnerShipStepTwo(), not instance with your argument.
so, please change FragmentHelper.NAVIGATE_FRAGMENT(moneyPartnerShipStepTwo, getActivity())
I have a StudentList fragment, which has a List; the Student class implements Parcelable; clicking an item in the StudentList fragment invokes the following StudentFragment:
public static StudentFragment newInstance(Student student_) {
StudentFragment fragment = new StudentFragment();
Bundle args = new Bundle();
args.putParcelable("STUDENT", student_);
fragment.setArguments(args);
return fragment;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Bundle args = getArguments();
if (args != null) {
mStudent = args.getParcelable("STUDENT");
}
}
private void setStudentName(String newName_) {
mStudent.setName(newName_);
}
This fragment is instantiated from another "StudentList" fragment, which has a List; an object from his list is provided as the parameter to StudentFragment.newInstance().
I was surprised to see that any changes to mStudent in the "StudentFragment" automatically get reflected on the corresponding object. On checking further in the onCreate method of StudentFragment, I found that the mStudent object reference is the same as the reference of the object that was passed to newInstance.
When I stepped through the code, I found that the Student.writeToParcel is never called.
How is this possible? Shouldn't I get a NEW object reference when I call mStudent = args.getParcelable("STUDENT") ?
Does the "arguments" bundle or the Parcelable interface preserve some link to the object reference, and use the parcel/unparceling as a last resort?
This post states that there's no guarantee that writing/reading to/from a Bundle will cause parceling/unparceling. Moreover it states that one shouldn't assume either behavior. This is probably why I keep getting back the exact same reference in onCreate.
Android Studio 0.8.7
I have the following function that sets some argument in the fragment:
public static Fragment newInstance(UUID uuid) {
Log.d(TAG, "newInstance: " + uuid);
Bundle arguments = new Bundle();
arguments.putSerializable(EXTRA_JOB_ID, uuid);
DetailFragment fragment = new DetailFragment();
fragment.setArguments(arguments);
return fragment;
}
In my onCreate() I retrieve the arguments using getArguments like this:
#Override
public void onCreate(Bundle savedInstanceState) {
Log.d(TAG, "onCreate()");
super.onCreate(savedInstanceState);
/* Get the arguments from the fragment */
UUID uuid = (UUID)getArguments().getSerializable(EXTRA_JOB_ID);
.
.
}
However, sometimes there is a situation where I won't be sending any arguments to be retrieved, and my program will crash in that case.
Using Intents has the hasExtra method to check this:
if(getActivity().getIntent().hasExtra(Intent.EXTRA_TEXT)) {
/* There is something to be retrieved */
}
I am wondering if there is something similar with getArguments
Many thanks in advance,
As an alternative suggestion to the other answers, your newInstance(...) method could be designed slightly better. As it stands, it always adds arguments even if your UUID parameter is null.
Try changing it to this...
public static Fragment newInstance(UUID uuid) {
Log.d(TAG, "newInstance: " + uuid);
DetailFragment fragment = new DetailFragment();
// Don't include arguments unless uuid != null
if (uuid != null) {
Bundle arguments = new Bundle();
arguments.putSerializable(EXTRA_JOB_ID, uuid);
fragment.setArguments(arguments);
}
return fragment;
}
Then in the onCreate(...) method of your Fragment check for arguments before anything else...
Bundle arguments = getArguments();
if (arguments != null && arguments.containsKey(EXTRA_JOB_ID))
UUID uuid = (UUID)arguments().getSerializable(EXTRA_JOB_ID);
Fragment.getArguments return an Bundle object all values send from other component. so you can use Bundle.containsKey for checking if key is available in received bundle or not:
Bundle bundle=getArguments();
if(bundle !=null)
if(bundle.containsKey(EXTRA_JOB_ID)){
// get value from bundle..
}
The purpose of the newInstance() design pattern AFAIK is that you guarantee your fragment will have the arguments supplied to it when it's instantiated.
In other words, the reason you call newInstance(something) is because you know something will be passed into the fragments argument, so you can always retrieve something from the fragment's getArguments() method later on.
So if you do plan on passing null as an argument, e.g. newInstance(null), which kind of defeats the purpose of using the newInstance design pattern, you're going to get a nullpointer exception.
You can call getIntent.containsKey(EXTRA_JOB_ID) to check whether your argument is null or not.