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.
Related
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 am working on Fragments, I would like to know whether it is possible to pass data from a fragment A to a fragment B directly, without forwarding the data to their attached Activity.
Use Bundle to send String:
//Put the value
YourNewFragment ldf = new YourNewFragment ();
Bundle args = new Bundle();
args.putString("YourKey", "YourValue");
ldf.setArguments(args);
//Inflate the fragment
getFragmentManager().beginTransaction().add(R.id.container, ldf).commit();
In onCreateView of the new Fragment:
//Retrieve the value
String value = getArguments().getString("YourKey");
There are number of ways you can do that. One of them is by sending data in arguments like this:
private int data;
private static String PARAM_MY = "param";
public static MyFragment newInstance(int data) {
MyFragment fragment = new MyFragment ();
Bundle args = new Bundle();
args.putInt(PARAM_MY , data);
fragment.setArguments(args);
return fragment;
}
and you can retreive it onCreate() :
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
data = getArguments().getInt(PARAM_MY);
}
}
Other way is to use Interfaces.
I don't think so. Every fragment is attached to an activity, there's no direct connection between two fragments, unless they are connected to the same activity. If you want to communicate between fragments, you'll have to define interfaces insides fragment and make the attached activity implement the interfaces. In the attached activity you have the two fragments instances, so you can pass (using the activity) data between fragments. It's strictly recommended by best practices, take a look at documentation for details:
https://developer.android.com/training/basics/fragments/communicating.html
If the activity is the same you can keep the data in the activity.
Activity
public class MyActivity extends Activity {
private MyObject myObject = new MyObject();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my);
...
}
public MyObject getMyObject() {
return myObject;
}
}
Fragment
public class MyFragment extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
MyActivity activity = (MyActivity) getActivity();
MyObject myObjectFromActivity = activity.getMyObject();
return view;
}
}
The main question would be what are you trying to achieve and what sort of data are you trying to pass?
One of the apps I wrote for work used the Main Activity to hold all the controllers so they could easily be accessed from any view, or framgment, or associated controller. A good example would be a data-controller holding all shared app data.
Are you looking to pass strings and ints, or more complex objects?
There are number of ways to achieve this
1 : Using Bundle
Link 1 - Explains How to transfer data using bundle and other methods
2 : Using Activities & Fragment
Link 2 - With help of activites ,interface and fragments
3: Using Shared Preferences
Shared Preferences Link
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.
For passing arguments to fragments, I see the best practice is to use a newInstance() method as such:
public static MyFragment newInstance(int myInt) {
MyFragment myFragment = new MyFragment();
Bundle args = new Bundle();
args.putInt("myInt", myInt);
myFragment.setArguments(args);
return myFragment;
}
and this would be instantiated as such:
int myInt = 123;
MyFragment myFragment = MyFragment.newInstance(myInt);
If I need to pass more variables then I would have to append whatever I'm adding to the newInstance() method. Example, if I'm also passing a string then my newInstance() method would look something like:
public static MyFragment newInstance(int myInt, String myStr) {
// code to put the int AND the string into the bundle
}
Now my question is: what's the difference between the above and below method, which passes the bundle?
public static MyFragment newInstance(Bundle args) {
MyFragment myFragment = new MyFragment();
myFragment.setArguments(args);
return myFragment;
}
instantiated by:
int myInt = 123;
Bundle args = new Bundle();
args.putInt("myInt", myInt);
MyFragment myFragment = MyFragment.newInstance(args);
I have been using the latter method so I can keep the parameter for newInstance() short. I have never seen an example using the latter method and I'm wondering if there is something wrong with it.
A bundle can hold multiple values.
Your first code can only send an integer value to the fragment, using a bundle you can send all you need in a single call.
Thats the main difference.
Hope this helps.
I'm sure this question has been asked lots of times but didn't find any useful answer.
I'm trying to implement Fragment which can be use in my app for X times (yes yes..even 100 and more..)
I want to create my fragment only once and in other times to pass bundle and make lifecycle do what he needs to do with the bundle data.
So far so good? So what i've found is a nice implementation from google document:
public static class MyFragment extends Fragment {
public MyFragment() { } // Required empty constructor
public static MyFragment newInstance(String foo, int bar) {
MyFragment f = new MyFragment();
Bundle args = new Bundle();
args.putString(ARG_FOO, foo);
args.putInt(ARG_BAR, bar);
f.setArguments(args);
return f;
}
You can then access this data at a later point:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Bundle args = getArguments();
if (args != null) {
// Use initialisation data
}
}
So what's wrong here? First, the Fragment MUST be an inner class. Second, if the class is static, and the function newInstance(...) is static, why they always create new instance without checking (By keeping a static member of the fragment) if it's not null like a Singleton ?
Assuming my fragment will be added many times to my fragment manager, can I use my fragment class as full Singleton? it means that each time I'll call:
public class MyFragment extends Fragment {
private static MyFragment sInstance;
public MyFragment() { } // Required empty constructor
public static MyFragment newInstance(String foo, int bar) {
if (sInstance==null) {
sInstance = new MyFragment();
}
Bundle args = new Bundle();
args.putString(ARG_FOO, foo);
args.putInt(ARG_BAR, bar);
f.setArguments(args);
return f;
}
}
Than use the new/exist fragment to make the transaction.
Hope I make myself clear, and didn't write some nonsense here :)
Thanks very much for your help