I am trying to pass string from Adapter to fragment in Bundle bu ti'm getting null in my Fragment
Here is my code to add string to Bundle
Bundle bundle=new Bundle();
bundle.putString("id",expense_id);
AddExpenseFragment fragment=new AddExpenseFragment();
fragment.setArguments(bundle);
UiActivity.startAddExpense(context);
this is my code to retrieve to Bundle value in Fragment
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
super.onCreateView(inflater, container, savedInstanceState);
View view=inflater.inflate(R.layout.activity_fragment_add_expense,container,false);
String id=this.getArguments().getString("id");
return view;
}
and i'm passing bundle value from My recyclerView Adapter class
The problem is simple here. You are creating a fragment and setting data to it which is fine,
AddExpenseFragment fragment=new AddExpenseFragment();
fragment.setArguments(bundle);
But the problem is in your
UiActivity.startAddExpense(context);
you must be replacing with a new instance of the AddExpenseFragment as you are no where passing the newly created fragment instance (with the arguments set to it) to the startAddExpense() method.
The solution is simple, just pass the newly created fragment object to the startAddExpense() like this,
UiActivity.startAddExpense(context, fragment);
and then inside the method replace or add this new fragment and do not instantiate any new fragment object.
Try this:
Bundle bundle = this.getArguments();
String id=bundle.getString("id");
From your code, it's hard to find problems.just give your some suggestions.
Firstly, check whether your variable expense_id is null or not.
Secondly, check whether the AddExpenseFragment you created and really showed are the same.
Related
I create the bundle in my Activity with
ListFragment fragment = new ListFragment();
Bundle bundle = new Bundle();
bundle.putInt("i", 0);
Log.i("Bundle", String.valueOf(bundle.getInt("i")));
fragment.setArguments(bundle);
And I get the arguments in my Fragment with
Bundle bundle = this.getArguments();
if (bundle != null) {
myInt = bundle.getInt("i", -1);
}
But it says that my bundle is null. Any idea why?
Are you sure that the fragment you want to read the arguments was created from the provided code block #1? Your code is correct, there is nothing wrong so it must work. (as long as the arguments are accessed after onCreate, which they are)
I had the same issue, I initially had my bundle variable declared outside the onCreateView function. Once I moved it inside, it worked for me
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 would like to pass an object from an activity to a fragment. I know how to pass the data but do not know which type of bundle i should use?
UPdate
In other words, I have an object of type mqttAndroidClient and that object i want to pass from my activity to a fragment through a bundle. Which bundle type I should use?
For relatively simple object data types, you shouldn't need a bundle at all. When you override onCreate() in the fragment that uses the argument, simply add a line of code that fetches the data from the intent.
For example, if you're passing an integer, the line would be:
intvar = (int)getActivity().getIntent().getInt(SOME_IDENTIFIER);
where SOME_IDENTIFIER is a constant that's common to both the activity and the fragment. (It would look something like "com.yourpackage.yourapp.some_identifier."
you should use something like this :
make your custom class that contains your desired data to be passed and extend from Serializable or Parcelable and put your object as extra to your Bundle object and set Bundle as an argument to your Fragment.
in your Activity
...
Fragment fragment = new YourFragment();
Bundle bundle = new Bundle();
bundle.putString("data", "yourData");
fragment.setArguments(bundle);
...
in your Fragment
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
String data = getArguments().getString("data");
...
}
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.
I have 2 fragments: (1)Frag1 (2)Frag2.
Frag1
bundl = new Bundle();
bundl.putStringArrayList("elist", eList);
Frag2 dv = new Frag2();
dv.setArguments(bundl);
FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.replace(R.id.the_fragg,dv);
ft.show(getFragmentManager().findFragmentById(R.id.the_fragg));
ft.addToBackStack(null);
ft.commit();
How do I get this data in Frag2?
Just call getArguments() in your Frag2's 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");
}
}
EDIT:
Best practice is read and save arguments in onCreate method. It's worse to do it in onCreateView because onCreateView will be called each time when fragment creates view (for example each time when fragment pops from backstack)
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Bundle arguments = getArguments();
}
Eg: Add data:-
Bundle bundle = new Bundle();
bundle.putString("latitude", latitude);
bundle.putString("longitude", longitude);
bundle.putString("board_id", board_id);
MapFragment mapFragment = new MapFragment();
mapFragment.setArguments(bundle);
Eg: Get data :-
String latitude = getArguments().getString("latitude")
You have a method called getArguments() that belongs to Fragment class.
in Frag1:
Bundle b = new Bundle();
b.putStringArray("arrayname that use to retrive in frag2",StringArrayObject);
Frag2.setArguments(b);
in Frag2:
Bundle b = getArguments();
String[] stringArray = b.getStringArray("arrayname that passed in frag1");
It's that simple.
Instantiating the Fragment the correct way!
getArguments() setArguments() methods seem very useful when it comes
to instantiating a Fragment using a static method.
ie Myfragment.createInstance(String msg)
How to do it?
Fragment code
public MyFragment extends Fragment {
private String displayMsg;
private TextView text;
public static MyFragment createInstance(String displayMsg)
{
MyFragment fragment = new MyFragment();
Bundle args = new Bundle();
args.setString("KEY",displayMsg);
fragment.setArguments(args); //set
return fragment;
}
#Override
public void onCreate(Bundle bundle)
{
displayMsg = getArguments().getString("KEY"): // get
}
#Override
public View onCreateView(LayoutInlater inflater, ViewGroup parent, Bundle bundle){
View view = inflater.inflate(R.id.placeholder,parent,false);
text = (TextView)view.findViewById(R.id.myTextView);
text.setText(displayMsg) // show msg
returm view;
}
}
Let's say you want to pass a String while creating an Instance. This
is how you will do it.
MyFragment.createInstance("This String will be shown in textView");
Read More
1) Why Myfragment.getInstance(String msg) is preferred over new MyFragment(String msg)?
2) Sample code on Fragments
for those like me who are looking to send objects other than primitives,
since you can't create a parameterized constructor in your fragment, just add a setter accessor in your fragment, this always works for me.
If you are using navigation components and navigation graph create a bundle like this
val bundle = bundleOf(KEY to VALUE) // or whatever you would like to create the bundle
then when navigating to the other fragment use this:
findNavController().navigate(
R.id.action_navigate_from_frag1_to_frag2,
bundle
)
and when you land the destination fragment u can access that bundle using
Bundle b = getArguments()// in Java
or
val b = arguments// in kotlin