Set arguments of fragment from activity - android

I want to pass arguments from my activity to a fragment, embedded into the activity. Fragment is embedded statically in xml layout.
I tried to call setArgument() like this:
setContentView(R.layout.detail_activity);
DetailFragment detailFragment = (DetailFragment) getFragmentManager().findFragmentById(R.id.detailFragment);
detailFragment.setArguments(getIntent().getExtras());
but it is already too late, because setArguments has to be called immediately after fragment's creation. The only was I see it to getArguments() and the change the bundle. Any better way?

AFAIK, you can't use setArguments() like that when you embed the fragment within XML. If it's critical, you'd be better off dynamically adding the fragment instead. However if you truly want the fragment to be embedded via XML, there are different ways you can pass along that data.
Have the Activity implement the fragment's event listener. Have the fragment then request the required parameters from the Activity at creation or whenever needed. Communication with Fragment
Create custom attributes that can be embedded in xml along with the fragment. Then during fragment's inflation process, parse the custom attributes to obtain their data. Custom fragment attributes
Create public setters in the fragment and have the activity use them directly. If it's critical to set them prior to the fragment's onCreate() method, then do it from the activity's onAttachFragment() method.

You have two options here
If you just need information in the activity's intent, then placing information from the intent into the fragment arguments just adds an unneeded step. You might just a well keep things simple and from your fragment call
Bundle data = getActivity().getIntent().getExtras();
If you need to add information that is not in the activity's intent then in you fragment create a no parameter constructor like:
public DetailFragment() {
this.setArguments(new Bundle());
}
then in your activity you can add whatever arguments you need with code like:
DetailFragment frg = (DetailFragment) getFragmentManager().findFragmentById(R.id.detailFragment);
frg.getArguments().putBundle("key", data);
the point here is to use the existing bundle object rather than trying to call setArguments() after the fragment has been attached to the activity.

Another way to pass data to Fragment is as following:
//In DetailFragment (for Instance) define a public static method to get the instance of the fragment
public static final DetailFragment getInstance(Bundle data) {
DetailFragment fragment = new DetailFragment();
fragment.setArguments(data);
return fragment;
}
And when attaching DetailFragment from inside Activity
Bundle data = new Bundle();
//Add data to this bundle and pass it in getInstance() of DetailFragment
fragmentTransaction.replace(R.id.frament_layout, DetailFragment.getInstance(data));

Related

Sending data to Fragment of Fragment from Activity (Activity->Fragment->Fragment) on menuItemclick

I am trying to send a data from MainActivity (on MenuItem click) to a Fragment of its Child Fragment.
I have shown an image to understand better.
I want an event to be fired in DayFragment from the MainActivity when MainActivity menuclicked.
I cannot send when the fragment is being created as you know.
Any ideas (or) code to understand the idea would be helpful.
Guys, Negative vote would neither help you nor me.
I will explain in little detail.
I am going to show a datepicker dialog fragment on menu item click on MainActivity. I need to pass the date from MainActivity -> calendarfragment - > dayfragment.
I want the date in dayfragment to other process. Thats it.
Create a public method inside Fragment which the Activity will call upon item selection.
From that public method, using the instance of ChildFragment, call another public method inside ChildFragment to make the magic happen!
You can use Fragment.setTarget(Fragment fragment, int requestCode); , just in case
Use a Bundle. Here's an example:
Fragment fragment = new Fragment(); // replace your custom fragment class
Bundle bundle = new Bundle();
FragmentTransaction fragmentTransaction = getSupportFragmentManager(). beginTransaction();
bundle.putString("key","value"); // use as per your need
fragment.setArguments(bundle);
fragmentTransaction.addToBackStack(null);
fragmentTransaction.replace(viewID,fragment);
fragmentTransaction.commit();
Bundle has put methods for lots of data types.
Then in your Fragment, retrieve the data (e.g. in onCreate() method) with:
Bundle bundle = this.getArguments();
if (bundle != null) {
int myInt = bundle.getInt(key, defaultValue);
}

How to transfer data from one activity to a fragment with Firebase?

Hey I was wondering how I could transfer data from one activity to a fragment using fire base. I have edit text in the activity class and a list view in the Fragment.
I would like to display the information throughout the app database so that other users can see and edit the information too.
I dont know if the IDE matters but passing information to a fragment is usually done with fragment arguments. You need to create a static "newInstance" method in your fragment that you can call from the activity and pass whatever info to the fragment through it. Something like this:
public static mListFragment newInstance(String fromActivity) {
mListFragment fragment = new mListFragment ();
Bundle args = new Bundle();
args.putString("STIRNG_FROM_ACTIVITY", fromActivity);
fragment.setArguments(args);
return fragment;
}
You can then call the method from the activity like this:
FragmentManager fm = getFragmentManager().beginTransaction();
mListFragment fragment = new mListFragment();
fragment = mListFragment.newInstance("info_to_send");
fragmentTransaction.add(R.id.fragments_frame, fragment);
From here you can even persist the info across device screen orientation changes..
Just use firebaseRef to setValue() and set the value from the edittext.
Add ValueListener on the fragment to get the same value from dataSnapshot.
:D
https://github.com/firebase/quickstart-java/tree/master/database/src/main/java/com/google/firebase/quickstart

Pass parameter from activity to fragment

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.

Unable to pass data to fragment through Bundle

I'm learning android fundamentals and I came across this problem while creating my first app. I have an activity which passes on data to a fragment. The OnCreate method of the activity has a block like this:
if(savedInstanceState == null){
DetailActivityFragment detailFrag = DetailActivityFragment.newInstance(movieId);
getSupportFragmentManager().beginTransaction().add(android.R.id.content,detailFrag).commit();
}
setContentView(R.layout.activity_detail);
At the fragment (activity_detail) if I perform getParameters(), I receive null. By playing around, I found that if I remove setContentView method from the snippet above, the fragment shows up with the data. Any ideas as to why that was a problem? Thanks!
Edit: Here is my static newInstance method in the fragment
public static DetailActivityFragment newInstance(String id) {
DetailActivityFragment fragment = new DetailActivityFragment();
Bundle args = new Bundle();
args.putString(Intent.EXTRA_TEXT, id);
fragment.setArguments(args);
return fragment;
}
Here's my fragment from the layout activity_detail:
<fragment android:name="app.appone.DetailActivityFragment"
android:id="#+id/fragment_detail"
android:layout_weight="1"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
You have to pass the data to your fragment.
Create a static method on your fragment for instance creation. It should look like this:
public static newInstance(Object param) {
DetailActivityFragment yourFragment = new DetailActivityFragment();
Bundle args = new Bundle();
args.put(key, value);
yourFragment.setArguments(args);
return yourFragment;
}
And in your onCreate method of the fragment you can get that data using the method "getArguments();
Your activity code is ok. But I would prefer using "replace" instead of "add" method.
Your latest edit shows you are using a static fragment in your layout xml, but creating it dynamically. A static fragment is created in your xml file:
<fragment android:name="app.appone.DetailActivityFragment"
android:id="#+id/fragment_detail"
android:layout_weight="1"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
Whereas a dynamic fragment is generated in your code with FragmentManager. It makes sense that calling setContentView() would cause a conflict, as the fragment you are creating with FragmentManager is being replaced by the fragment you are defining in your xml file. The one in your xml, unlike your dynamic fragment, has no arguments, which is why it's returning null.
As you use android.R.id.content, you can remove this static fragment from your xml completely. Replace it with an empty layout, such as FrameLayout, and set an id attribute. Then, when using FragmentManager, replace android.R.id.content for this id.
For example:
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/frag_container" />
And in your Activity file:
DetailActivityFragment frag = (DetailActivityFragment) getSupportFragmentManager().findFragmentById(R.id.frag_container);
if (frag == null) {
frag = DetailActivityFragment.newInstance(id);
getSupportFragmentManager()
.beingTransaction()
.add(R.id.frag_container, frag)
.commit();
}
Thanks for your edit. I think you are using the wrong id for fragment replacement.
As in a previous comment you should first set the content view. Your layout file should have a placeholder view, e.g. Framelayout. Give your layout an id and reference this id in your replacement code.
Your "R.layout.activity_detail" should have a layout snippet like this:
<FrameLayout id="+#id/my_detail_frag"/>
And your activity code should look like this:
getSupportFragmentManager().beginTransaction().add(R.id.my_detail_frag,detailFrag).commit();
This answer will do the trick for you:
Best practice for instantiating a new Android Fragment
You should use setArguments() and getArguments() to pass the Bundle into the Fragment.
Good luck!

Android Fragments sharing info ways

i have a internal discussion about what way is better to share info between fragments contents inside a controller activity. In a first classical way, you can set arguments when you are going to replace fragments as follows:
//Just now i'm inside Fragment 1 and i'll navigate to Fragment 2
Fragment newFragment = getFragmentManager().findFragmentByTag(Fragment2.TAG);
Bundle b = new Bundle();
b.putBoolean("test1", true);
// Create new fragment and transaction
if(newFragment==null)
newFragment = Fragment2.newInstance(b);
FragmentTransaction transaction = getFragmentManager().beginTransaction();
transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN)//.setCustomAnimations(R.anim.enter_anim, R.anim.exit_anim)
.replace(R.id.fragment_place, newFragment, Fragment2.class.getName())
.addToBackStack(newFragment.getClass().getName())
.commit();
The newInstace method does as i meant above, so, with setArguments:
public static Fragment2 newInstance(Bundle arguments){
Fragment2 f = new Fragment2();
if(arguments != null){
f.setArguments(arguments);
}
return f;
}
But Fragment1 and Fragment2 they are both inside a ControllerActivity, so i can also think about a second way to share information obtained in Fragment1 towards Fragment2, through declaring attributes in the ControllerActivity, so i could do (declaring previously an object in the activity) as follows inside any fragment:
EDIT
public class ControllerActivity extends FragmentActivity{
int value = 5;
...
And then, inside my fragment:
((SplashActivity)getActivity()).value = 10; //i can assign or recover value when i desire
My question is what inconveniences would have doing as the second way.
Writing code using 2nd way is fast. But the problem is you have to cast the general Activity to the more specific SplashActivity in which the value variable exists. If you want to use the Fragment with another Activity, or you want a Fragment to be a general purpose UI component you have to use interface for passing the data.
As mentioned in comments, bellow links provide more details about interface/callback method:
android docs
video from slidenerd
Hope this answers your question.

Categories

Resources