Currently I have been diving into the Fragment world: http://developer.android.com/guide/components/fragments.html#CommunicatingWithActivity
I understand that by creating a listener in the fragment and then implementing it in the Activity which hosts the fragment is a great way to communicate from the fragment to the Activity, but how do I get communicate back from the activity to the fragment? Another listener? Perhaps I don't fully understand what the listener is doing. Any help with this topic explaining how to communicate from activity to fragment would be much appreciated!
P.S. I am currently converting an activity (B) that I made into a fragment. I use to do some intent.putExtra("value") from Activity A before starting Activity B so this is what I am looking to replace... Probably doesn't help you at all but I thought I'd try and put it into perspective what I am doing.
I may have found the solution, lol. I'll do some checks to make sure this works and confirm it later.
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
Bundle b = getActivity().getIntent().getExtras();
wid = b.getString("wid");
rid = b.getString("rid");
View view = inflater.inflate(R.layout.categoryfragment, container, false);
return view;
}
Just like you do when you create an Activity, you can pass a Bundle to a Fragment.
There's an example on how to do that on the Fragment class reference.
/**
* Create a new instance of DetailsFragment, initialized to
* show the text at 'index'.
*/
public static DetailsFragment newInstance(int index) {
DetailsFragment f = new DetailsFragment();
// Supply index input as an argument.
Bundle args = new Bundle();
args.putInt("index", index);
f.setArguments(args);
return f;
}
Use getArguments() to get the Bundle back.
Related
This question already has answers here:
Send data from activity to fragment in Android
(22 answers)
Closed 5 years ago.
I have passed some key and value data from one activity to another activity fragment so I have not get key and value to the last point in the fragment.
I have passing data using bundle.
In your activity create bundle to set to the fragment
Yourfragment fragment = new Yourfragment();
Bundle args = new Bundle();
args.putString(ARG_DATA, data);
fragment.setArguments(args);
Then load the fragment getSupportFragmentManager().beginTransaction().replace(R.id.your_container,fragment).commit();
Then in your fragment oncreate get the data like this
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
mData = getArguments().getString(ARG_DATA);
}
}
From activity to activity you can pass data by using Intent and when you get data in second activity in which you are creating fragments on creating fragment pass that data to fragment by making constructor in fragment or by using bundle. For further assistance and if you dont know how to do this do let me know.
Pass data from activity to activity:
Intent intent = new Intent(this, Second.class);
intent.putExtra("data", sessionId);
startActivity(intent);
get data in Second activity:
String s = getIntent().getStringExtra("data");
Pass data from activity to fragment:
Bundle bundle = new Bundle();
bundle.putString("data", "From Activity");
// set Fragmentclass Arguments
FragmentOne fragment = new FragmentOne ();
fragment.setArguments(bundle);
get data from activity to fragment:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
String strtext = getArguments().getString("data");
return inflater.inflate(R.layout.fragment, container, false);
}
Happy coding!!
You can pass data between Activity and Fragments and Fragment to fragment using below:
https://developer.android.com/training/basics/fragments/communicating.html
But to pass it between activity, you may use bundle data, (very few variables) or use Application Class to store it in memory, make sure you do not bloat up your memory.
New Android architecture components also do provide good options, it all depends upon your use:
https://developer.android.com/topic/libraries/architecture/index.html
Right now I'm making an app that requires me to have about 20 or more different pages/layouts, one loaded at a time, but little/no intercommunication between them. They would be very static. Right now I had the idea to have one activity, one fragment that would inflate a different layout in the onCreateView, and the fragment would be reloaded everytime the user selected another page. However I just realized that wouldn't work at all because I can't put the return statement of onCreateView in an if statement, and no workaround work.
So now I don't know the most efficient way to do this. There's no way having 20+ layouts and 20+ classes, one for each page is ideal. It seems very redundant.
You can use the Fragment's bundle to communicate to it which layout to use.
In the Fragment class, create a static method to create the Fragment instance and set it's bundle, for example:
public static MyFragment newInstance(int layoutId) {
MyFragment f = new MyFragment();
Bundle args = new Bundle();
args.putInt("layoutId", layoutId); // e.g. layoutId = R.layout.layout_fragment_01
f.setArguments(args);
return f;
}
and then in the fragment's onCreateView, get the layout id from the bundle:
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return inflater.inflate(getArguments().getInt("layoutId", 0), container, false);
}
then, in your Activity, you'd do something like the following:
MyFragment fragment = MyFragment.newInstance(R.layout.fragment_layout_01);
getFragmentManager().beginTransaction().add(android.R.id.content, fragment).commit();
I have seen Bundles restored in several of the Android callback methods, but in many cases there is manual creation and setting of Bundles as on the developers website, in this case from an external message on Fragment creation:
public static DetailsFragment newInstance(int index) {
DetailsFragment f = new DetailsFragment();
// Supply index input as an argument.
Bundle args = new Bundle();
args.putInt("index", index);
f.setArguments(args);
return f;
}
In this other question, for example, bundle data is restored in the onCreateView() method.
public class Frag2 extends Fragment {
public View onCreateView(LayoutInflater inflater,
ViewGroup containerObject,
Bundle savedInstanceState){
//here is your arguments
Bundle bundle=getArguments();
//here is your list array
String[] myStrings=bundle.getStringArray("elist");
}
}
I am a bit confused about the Bundle data supplied with each callback method VS "other bundles":
Bundle bundle=getArguments();
and the correct way and place to retrieve these different types of bundled data.
Thanks in advance!
The two ways described above are exactly the correct way to
initialize a new instance of the Fragment and pass the initial parameters.
retrieve the initial parameters in the Fragment.
In other words, you're on the right track! It should work, and you should be pleased with yourself :)
EDIT:
The Bundle can be retrieved in either onCreateView() or
onCreate(). I'd prefer onCreate(), as it represents the creation
of the Fragment instance and is the right place for initialization.
There is always one and only one Bundle instance retrieved by the call to getArguments(), and this Bundle instance contains all of your ints, Strings, whatever.
I am creating an app in which the user should be able add people for meetings.
The structure consists of several fragments managed in the same activity (list_people, person_detail, create_meeting).
I would like to reuse the fragment showing the list of people as a dialog in the create_meeting fragment. And add a person to a meeting by clicking on the person item.
When the list_people fragment is embedded in the view, a click on a person item replace the list_people fragment with a person_detail fragment. This behavior is already implemented with an interface for the main activity.
I am looking for a solution to change the behavior of the click listener whether the list_people fragment is displayed as an embedded fragment or as a dialog. Any ideas of how I could do that?
Any help would be greatly appreciated.Thanks.
Ok I have found a solution. It is to use a constructor (newInstance) for the fragment in which you can pass variables.
public class ListPeopleFragment extends Fragment {
public static ListPeopleFragment newInstance(boolean nested){
ListPeopleFragment f = new ListPeopleFragment();
Bundle args = new Bundle();
args.putBoolean("nested", nested);
f.setArguments(args);
return f;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){
View view = inflater.inflate(R.layout.fragment_list_people, container, false);
boolean nested = false;
Bundle arguments = getArguments();
if (arguments != null)
{
nested = getArguments().getBoolean("nested");
}
displayListViewPeople(view, nested);
return view;
}
}
The displayListViewPeople set the click listener depending on the value of nested.
You instantiate the fragment this way:
ListPeopleFragment nestedFrag = ListPeopleFragment.newInstance(true);
I was just wondering how I could send parameters or arguments to a Fragment before it is created. Because I want to pass an array of strings to the fragment so that it could put all of them in the layout when it is created. For example I am making a Leaderboard fragment, and my activitiy would pass in all of the scores etc. that the fragment would use to display. I understand that I can use the Bundle and the .setArgs but will that work for my case?
Thank you
** EDIT **
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View singleplayerView = inflater.inflate(R.layout.singleplayer_tab, container, false);
String[] scores = (String[]) getArguments().get("scores");
TextView tview = (TextView) singleplayerView.findViewById(R.id.player_name0);
tview.setText(scores[0]);
setupRank(singleplayerView);
return singleplayerView;
}
public static SingleplayerTab newInstance(String[] scores) {
SingleplayerTab spt = new SingleplayerTab();
Bundle args = new Bundle();
args.putStringArray("scores", scores);
spt.setArguments(args);
return spt;
}
CODE THAT CALLS IT
String[] scores = {"hello"};
Fragment singlePlayerFragment = SingleplayerTab.newInstance(scores);
I understand that I can use the Bundle and the .setArgs but will that work for my case?
A Bundle can hold an String[] or an ArrayList<String>.
Moreover, this is the way you should do it, rather than a custom constructor. Android automatically recreates your fragments on a configuration change (e.g., screen rotation), and it will use your public zero-argument constructor for that. Hence, unless you use the arguments Bundle, or something else, you will lose your string array on a configuration change.
The recommended approach for this is to use a factory method, such as this one from an EditorFragment:
static EditorFragment newInstance(int position) {
EditorFragment frag=new EditorFragment();
Bundle args=new Bundle();
args.putInt(KEY_POSITION, position);
frag.setArguments(args);
return(frag);
}
In this case, I want to pass int position into the fragment. I isolate packaging this into the Bundle into the factory method (newInstance()). When I need to create an instance of this fragment, I call EditorFragment.newInstance() instead of new EditorFragment, so I can supply the position. My fragment can get the position by reading the KEY_POSITION value out of the getArguments() Bundle. I use this approach in (among other places) this sample project, showing loading 10 of these editors into a ViewPager.