How can I get a value(String) from activity and then use it in Fragment?
errors are occurred
fragment.java
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
String strtext = getArguments().getString("edttext");
View rootView = inflater.inflate(R.layout.fragment_user_info,
container, false);
return rootView;
}
activity.java
Bundle bundle = new Bundle();
bundle.putString("edttext", "From Activity");
UserInfoFragment fragobj = new UserInfoFragment();
fragobj.setArguments(bundle);
The error is a NullPointerException, correct?
This is because you read the arguments (in the fragment's constructor):
String strtext = getArguments().getString("edttext");
before you assign them (in activity after the fragment's constructor has already been called):
fragobj.setArguments(bundle);
Keep the constructor simple. Best solution is to create a static factory method newInstance(String edttext) according to this guide https://stackoverflow.com/a/9245510/2444099 like so:
public static UserInfoFragment newInstance(String edttext) {
UserInfoFragment myFragment = new UserInfoFragment();
Bundle args = new Bundle();
args.putInt("edttext", edttext);
myFragment.setArguments(args);
return myFragment;
}
Then use this factory method instead of constructor whenever you need to obtain a new fragment instance.
This is what's happening in your current code:
You create the Fragment
In the onCreateView() method, you get the arguments
You set the arguments in your Activity.
In other words, you're calling the arguments before you've set them. As per the Fragment Documentation, you should be using a static method to instantiate your Fragments. It would look something like the following.
In your Fragment class, add this code
/**
* Create a new instance of UserInfoFragment, initialized to
* show the text in str.
*/
public static MyFragment newInstance(String str) {
MyFragment f = new MyFragment();
// Supply index input as an argument.
Bundle args = new Bundle();
args.putString("edttext", str);
f.setArguments(args);
return f;
}
And now, in your Activity, do the following:
//Bundle bundle = new Bundle();
//bundle.putString("edttext", "From Activity");
//UserInfoFragment fragobj = new UserInfoFragment();
//fragobj.setArguments(bundle);
UserInfoFragment fragobj = UserInfoFragment.newInstance("From Activity");
Notice how now, you don't even need to create a Bundle and set it in your Activity class, it is handled by the static newInstance() method.
Related
I want to receive data from class to fragment by Intent ,I try to do ,I write
Intent n = this.{getIntent()};
{the wrong here} ,but this code is not working ,so what i do ?
Activity Send Intent data to fragment
Bundle b = new Bundle();
b.putString("data", "abc");
// set Fragmentclass Arguments
Fragment frag = new Fragment();
frag.setArguments(b);
Fragment receive data with intent
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
String data = getArguments().getString("data");
return inflater.inflate(R.layout.fragment, container, false);
}
For fragments, you can visit Send data from activity to fragment in android
Try this,
you can send data from activity using,
Bundle bundle = new Bundle();
bundle.putString("key", "value");
Fragmentclass fc= new Fragmentclass();
fc.setArguments(bundle);
and receive from this way in your fragment's onCreateView method,
String strtext = getArguments().getString("key");
that's it
I have a question.
I was coding some help pages using Fragment.
public HelpFragment(int i) {
Bundle args = new Bundle();
args.putInt("page", i);
setArguments(args);
}
In test case, I got this error.
"make sure class name exists, is public, and has an empty constructor that is public"
So that, I added empty constructor.
public HelpFragment() {
Bundle args = new Bundle();
args.putInt("page", 0);
setArguments(args);
}
But still that error is producing.
What should do I?
Thanks in advance.
Don't override constructor at all. Instead create public static method:
public static HelpFragment newInstance(int i) {
HelpFragment f = new HelpFragment();
Bundle args = new Bundle();
args.putInt("page", i);
f.setArguments(args);
return f;
}
how you call your fragment to your application? I think you SHOULD NOT override the constructor if you use fragment, and put your arguments in onCreate or onCreateView instead
if you use fragment i think onCreateView is better
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
//your arguments here
return inflater.inflate(R.layout.fragment_help_layout, container, false);
}
I'm totally stupid.
I have been missing add this in code.
super()
But I don't 100% trust about this solution.
I'll report if I see this error in Google Play crashes.
I want to receive data from an Activity to a Fragment.
In an Activity is easy:
Bundle b = getIntent().getExtras();
String flag = b.getString("flag");
Ok, for me, doesn't work
String flag = getIntent().getExtras().getString("flag");
Neither
String flag = getActivity().getIntent().getExtras().getString("flag");
Or.
Bundle b = getIntent().getExtras();
The error: "Unreachable code"
Any idea?
You can view that on Fragment documentation.
Create a newInstance funcion in your fragment to initialize the fragment and add data with setArguments, passing a Bundle.
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;
}
Then get the arguments using:
Bundle args = getArguments();
int index = args.getInt("index", 0);
I have an enum describing three different sports:
public enum MatchType {
S1(0, "Sport1", "xml stream address", R.id.match_list, R.layout.fragment_match_list, R.color.separator_sport1),
S2(0, "Sport2", "xml stream address", R.id.match_list, R.layout.fragment_match_list, R.color.separator_sport2),
S3(0, "Sport3", "xml stream address", R.id.match_list, R.layout.fragment_match_list, R.color.separator_sport3);
...getters/setters
}
I then have fragment with
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
matchesArrayAdapter = new MatchListAdapter(getActivity(), new ArrayList<Match>());
return inflater.inflate(matchType.getLayout(), container, false);
}
Also in my fragment I have an AsyncTask where I have this
#Override
protected void onPostExecute(final List<Match> matches) {
if (matches != null) {
matchListView = (ListView) getActivity().findViewById(matchType.getRId());
[setup listeners]
matchesArrayAdapter.matchArrayList = matches;
matchListView.setAdapter(matchesArrayAdapter);
}
}
EDIT:
In my Activity I have an AppSectionsPagerAdapter with
public Fragment getItem(int i) {
MatchListSectionFragment fragment = new MatchListSectionFragment();
Bundle bundle = new Bundle();
bundle.putInt(Constants.MATCH_TYPE, i);
fragment.setArguments(bundle);
return fragment;
}
EDIT 2:
Here's my onCreate and onCreateView from my fragment:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Bundle bundle = getArguments();
matchType = MatchType.getMatchType(bundle.getInt(Constants.MATCH_TYPE));
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
matchesArrayAdapter = new MatchListAdapter(getActivity(), new ArrayList<Match>());
return inflater.inflate(matchType.getLayout(), container, false);
}
The AsyncTask reads an xml stream for each of the sports in my enum but my problem is that tab #1 is overwritten with data from tab #2 and subsequently tab #3.
Before I had a fragment defined for each sport but surely that can't be necessary?
How do I go about using the same fragment with the same layout for each sport?
When instantiating your fragment in your Activity set the Fragment's arguments with a Bundle.
Bundle myBundle = new Bundle();
myBundle.putInt(MY_EXTRA, 1);
myFragment.setArguments(myBundle);
In your bundle put some Extra that will be read in the fragment's onCreate() callback.
int i = getArguments().getInt(MY_EXTRA);
I am on mobile.
Put three FrameLayouts in a LinearLayout, named frame1, frame2 and frame 3. This will be your main Activity's layout.
Then in the Activity's oncreate() method, call getFragmentManager().getFragmentTransaction().
Instantiate the three fragments and send them the data, preferably through a Bundle.
On the Fragment Transaction call the add() or replace() method for each fragment, the first parameter is the id of the respective FrameLayout, the second parameter is the fragment itself.
Call commit().
You should create the newInstance method in your fragment, also you should store MatchType instansce in you fragment.
MatchType matchType;
public static MyFragment newInstance(MatchType matchType) {
MyFragment fragment = new MyFragment();
fragment.matchType = matchType;
return fragment;
}
In your Activity you should to create 3 instances of MyFragment with this method (with related to each fragment it owns MatchType). Then in onCreateView method you should insert data to your views from matchType.
Sorry, I'm on mobile. And sorry for my English.
Update
Check your variable matchType. Maybe it declared as static?
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