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.
Related
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.
If I create a new Fragment and then I set arguments to it can I rely on those arguments always being available for me in the onCreate() of the Fragment? If yes, how do they do it? If not how I'am I supposed to communicate if they don't want us to write new constructors?
Try this way any fragment to set argument and get argument..
// pass parameter to pass into bundle
public static NewMessageFragment newInstance(UserData userData) {
NewMessageFragment newMessageFragment = new NewMessageFragment();
Bundle bundle = new Bundle();
bundle.putParcelable(Constants.KEY_MESSAGE_USER_VO, userData);
newMessageFragment.setArguments(bundle);
return newMessageFragment;
}
// get value.
private void extractArguments() {
Bundle bundle = getArguments();
if (bundle != null) {
userData = bundle.getParcelable(Constants.KEY_MESSAGE_USER_VO);
}
}
extractArguments() method called into onCreateView() method.
Yes, your arguments are avaialble in onCreate method. Please check it out this response in order to see how to pass arguments to fragments: How to transfer some data to another Fragment?
Another way to communicate with the fragment is via a interface that your activity is implementing and you pass it as a reference to your fragment, in onAttach method. More info:
https://developer.android.com/training/basics/fragments/communicating
Basic Communication between two fragments
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.
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...
If I set arguments of a fragment myfragment to a Bundle mybundle, am I guaranteed that if I change the contents of mybundle later down the road, myfragment's call to getArguments() will be consistent with the contents of mybundle?
i.e.
mybundle.putString("background", "red");
myfragment.setArguments(mybundle);
... later ...
mybundle.putString("background", "orange");
myfragment.createLayoutFromBundle(myfragment.getArguments());
Yes. Check the source code for the Fragment class. The bundle is not copied or anything, just returned as-is.
public void setArguments(Bundle args) {
if (mIndex >= 0) {
throw new IllegalStateException("Fragment already active");
}
mArguments = args;
}
/**
* Return the arguments supplied when the fragment was instantiated,
* if any.
*/
final public Bundle getArguments() {
return mArguments;
}
The arguments Bundle is part of the fragment's saved instance state. If the fragment is destroyed and re-created, your newly-created fragment will have an arguments Bundle with the same contents as did the original Bundle. However, the Bundle object may be different.
This will most easily seen when:
the user is in your fragment, with the Bundle
the user presses HOME
your process is terminated (you can test this via DDMS)
the user returns to your fragment via the recent-tasks list
You will have the same data in the Bundle as before, but the Bundle object will be newly-created.