I am tyring to add a fragment in a navigation Drawer and some of the data have to pass to the fragment,
but getArgument returns null and I still cannot solve the problem after reading the similar question.
In my drawer class, the fragment is added by
Bundle args = new Bundle();
args.putString("username",username);
args.putString("password",password);
UserLoginFragment alreadyLoginFragment = new UserLoginFragment();
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
alreadyLoginFragment.setArguments(args);
fragmentTransaction.add(R.id.drawer_User_Container, alreadyLoginFragment, "alreadyLogin");
fragmentTransaction.commit()
;
And in the fragment, the argument is get by :
String username;
String password;
public UserLoginFragment(){
Bundle args=getArguments();
if(args!=null){
Log.d("test","have args");
}
else{
Log.d("test","no args");
}
}
And the log will be no args
Dont call getArgument() in the constructor, at the time the constructor is called, the argument bundle has not yet been set, so it will return null every time no matter what you do. Call it like this
#Override
public void onAttach(Activity act)
{
Bundle args = getArguments();
}
You are just recieving the argument. You must recieve the content that was passed in the argument.
String username = getArguments().getString("username");
String password = getArguments().getString("password");
Related
Hi I'm learning now about Fragments and I have some doubts.
V1:
So the correct way to create a new Fragment should be with "newInstance" instead of a constructor and would be something like this:
Fragment fragment = MyFragment.newInstance(variable);
And the code on the class "MyFragment" should be this:
private static final String ARG_PARAM1 = "param1";
private int variable;
public MyFragment() {
//Empty constructor
}
New instance will receive the param and will put them on a Bundle and set the argument for the class
public static mi_fragment newInstance(Int param1) {
MyFragment fragment = new MyFragment();
Bundle args = new Bundle();
args.putInt(ARG_PARAM1, param1);
fragment.setArguments(args);
return fragment;
}
Then after setting it the method onCreate will pick up the argument:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
variable = getArguments().getInt(ARG_PARAM1);
}
V2:
But I still can't see the problem with using the constructor and setting the arguments programatically:
Bundle bundle = new Bundle();
bundle.putInt("key", variable);
Fragment fragment = new MyFragment();
fragment.setArguments(bundle);
Then I pick up the argument on the method onCreate:
public void onCreate(#Nullable Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
Bundle bundle = this.getArguments();
if(bundle!=null){
variable = getArguments().getInt("key");
}
}
So I decided to search on the internet about this and I found a good answer but I still can't seem to understand it or when you could use it.
the way to pass stuff to your Fragment so that they are available after a Fragment is recreated by Android is to pass a bundle to the setArguments method.
This Bundle will be available even if the Fragment is somehow recreated by Android.
So my conclusion is that you keep the bundle alive and using the newInstance could make you return to the last fragment for example. But probably I'm wrong so I need help.
Question: What's the main difference between both and how do you benefit from newInstance ? An example.
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.
I have a problem with pass data from activity to fragment, it says null pointer exception, but my data is not null.
This is my activity :
#Override
public void onResponse(Call call, Response response) throws IOException {
dataj = response.body().string();
System.out.println(dataj);
Bundle bundle = new Bundle();
bundle.putString("datak", dataj);
FragmentUtama fu = new FragmentUtama();
fu.setArguments(bundle);
Intent load = new Intent(LoginActivity.this, MainActivity.class);
load.putExtra("datajs", dataj);
startActivity(load);
finish();
}
and this is my fragment :
public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {
// Inflate the layout for this fragment
String datas = getArguments().getString("datak");
System.out.println(datas);
return inflater.inflate(R.layout.fragment_utama, container, false);
}
Thanks for your help.
You don't pass data to fragment via Intents. Arguments are passed by setting them to the fragment instance before calling Fragment transaction commit.
SomeFragment f = new SomeFragment ();
// Supply data input as an argument.
Bundle args = new Bundle();
args.putInt("some_key", value);
f.setArguments(args);
then you read it in your fragment.
NOTE: setArguments can only be called before the Fragment is attached to the Activity. So if fragment is already attached, it will not transfer any data to the fragment.
Bundle args = getArguments();
int value = args.getInt("some_key", 0);
you may try this,
use findFragmentByTag it will help you to find fragment and send data over it.
FragmentUtama fu =(FragmentUtama)getSupportFragmentManager().findFragmentByTag(FragmentUtama.class.getSimpleName())
Bundle bundle = new Bundle();
bundle.putString("datak", dataj);
fu.setArguments(bundle);
or
you can have one setter method in fragment and set data from activity to fragment
from Activity.
fu.setData(dataj);
In fragment
String data;
public void setData(String data)
{
this.data=data;
}
use data using getter method of fragment
public String getData()
{
return data;
}
You need to pass the data to MainActivity using extras of an intent and then using setArguments to pass it to the fragment that belongs to this activity when replacing/adding that fragment to its container.
I want to pass a complex object between activity and fragments as well as fragments and fragments. Currently, the main activity create a fragment input object and set that as a member of the fragment needed to be open. Similarly, when another fragment wants to load another fragment it creates fragment input and notifies the main activity. See Main and child fragment code below. My question, is this correct implementation. Sometimes I encountered input being null in child activity, if the activity pauses and restarts.
Please tell me what I have done wrong, whats the best way to pass data.
public class FragmentInput {
public String url = "";
public String title = "";
public String time = "";
... other memebers
}
Main Activity
fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager
.beginTransaction();
BaseFragment fragment = new LandingFragment();
**FragmentInput input = new FragmentInput();
input.stringinput = stringinput;
fragment.input = input;
fragmentTransaction.replace(R.id.fragment, fragment);
fragmentTransaction.commit();**
public void replaceFragment(BaseFragment fragment) {
if (fragment == null)
return;
if (fragment instanceof firstFragment) {
FragmentTransaction fragmentTransaction = fragmentManager
.beginTransaction();
fragmentTransaction.setCustomAnimations(0, 0);
fragmentManager.popBackStackImmediate(null,
FragmentManager.POP_BACK_STACK_INCLUSIVE);
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
} else {
String ttag = fragment
.getClass().toString();
Fragment tempF = fragmentManager.findFragmentByTag(ttag);
if (tempF != null)
return;
FragmentTransaction fragmentTransaction = fragmentManager
.beginTransaction();
fragmentTransaction.setCustomAnimations(R.anim.fragment_enter,
R.anim.fragment_exit, R.anim.fragment_leftenter,
R.anim.fragment_leftexit);
fragmentTransaction.replace(R.id.fragment, fragment, ttag);
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
}
}
ChildFragment
#Override
public void onActivityCreated(Bundle bundle) {
super.onActivityCreated(bundle);
try {
activity = getActivity();
resource = activity.getResources();
view = getView();
**if (input != null) {
String url= input.url;**
button.onclick(){
FragmentInput input = new FragmentInput();
input.url = path;
input.title = resource.getString(R.string.txt_from_gallery);
**BaseFragment fr = new otherFragment();
FragmentChangeListener fc = (FragmentChangeListener) getActivity();
fr.setInput(input);
fc.replaceFragment(fr);**
}
}
If your fragments attach to same activity, you can store your objects in activity and access to objects like below:
((YourActivity)getActivity()).getYourObjects();
If you are storing your objects in bundle in you activity i recommand to call the code sample i gave above in onActivityCreated() method of your fragments to avoid null pointer exception.
If you want to pass your objects between activities or fragments in bundle. You should implement Parcelable to your objects and pass them.
What's Parcelable?
http://developer.android.com/reference/android/os/Parcelable.html
Parcelable is more efficient but you can check Serializable:
http://developer.android.com/reference/java/io/Serializable.html
It's not a good design to pass large objects in bundle.
Also you can pass your objects with interfaces or you can pass them with bus events. You can check Guava or OttoBus.
http://square.github.io/otto/
In this case you can use static holder (it's a bit similar to a singleton pattern).
Create a new class
public class Holder
{
private static FragmentInput input = null;
public static void setInput(FragmentInput value) { this.input = value; }
public static FragmentInput getInput() { return input; }
}
In your main activity, after you create your new FragmentInput object
hold it on the Holder
Holder.setInput(input);
And you can access it anywhere, simply call
FragmentInput myInput = Holder.getInput();
I am currentley launching new activities and passing data liek this:
Intent myIntent = new Intent(c, TastePage.class);
myIntent.putExtra("taste", tempTaste);
c.startActivity(myIntent);
and then retrieving the data in the new activity with:
//get data from listview
Bundle extras = getIntent().getExtras();
String taste = extras.getString("taste");
In order to follow android design guidelines better I am implementing a navigation drawer and changing my activities into fragments. I am just a little confused on how to pass data between fragments.
For loading new fragments I am using this code:
FragmentManager man=getFragmentManager();
FragmentTransaction tran=man.beginTransaction();
Fragment_two=new BPTopTastes();
tran.replace(R.id.main, Fragment_two);//tran.
tran.addToBackStack(null);
tran.commit();
what can I implement into that code to pass data to the new fragment, and how can I retrieve that data in the new fragment?
Use a bundle:
Send data from source fragment
Fragment fragment = new Fragment();
final Bundle bundle = new Bundle();
bundle.putString("user_name", myusername);
fragment.setArguments(bundle);
And read from target fragment
Bundle args = getArguments();
if (args != null && args.containsKey("user_name"))
String userName = args.getString("user_name");
It is not the best idea but you can also use setters to set some values. You don't have to use Bundle.
public class YourFragment extends Fragment{
private String mUserName;
public void setUserName(String userName) {
mUserName = userName;
}
}
......
FragmentTransaction tran = getSupportFragmentManager().beginTransaction();
YourFragment fragment = new YourFragment();
fragment.setUserName(myUserName);
tran.add(R.id.main, fragment, "frag");
tran.addToBackStack(null);
tran.commit();
you could use Singleton Class to pass information between any component on your android process
you could access them from your services / activities / fragments ....
for example
class GlobalVars{
private GlobalVars global;
private String taste;//generate get/set
public static GlobalVars getinstance(){
if(global==null){global = new GlobalVars();}
return global}}
}
//By Calling
GlobalVars.getinstance()
//you will have a common access to the variables inside the class