1

I have a fragment which shows a list of buttons, each have their own id. When the user clicks the button, I am trying to replace the current fragment with another. Right after I replace the fragment, I a am adding arguments to the bundle. From what I can tell from debug mode, that part is working 100%. However, when we get to the new fragment, the "savedInstanceState" state will always be null.

I have read several posts on this however, I am confused because I am attempting to set the bundle and replace the fragment the same way I did when going from the activity to the first fragment and it is still not working.

MyActivity.java (this is working and all values are being set):

protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
MyFirstFragment fragment = new MyFirstFragment();
        FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
        fragmentTransaction.replace(R.id.frame,fragment);
        fragmentTransaction.commit();
        Intent i = getIntent();
        value = i.getExtras().getString("key");
        Bundle bundle = new Bundle();
        bundle.putString("key",value);
        fragment.setArguments(bundle);
}

MyFirstFragment.java (also working):

public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_first, container, false);
final String value = getArguments().getString("key");
myButton.setOnClickListener(new View.OnClickListener(){
                    @Override
                    public void onClick(View v){
                        String gid = Integer.toString(v.getId());

                        MySecondFragment secondfragment = new MySecondFragment();
                        Bundle secondFragmentBundle = new Bundle();
                        secondFragmentBundle.putString("key",value);
                        secondFragmentBundle.putString("id",id);
                        secondfragment.setArguments(secondFragmentBundle);

                        FragmentTransaction fragmentTransaction = getFragmentManager().beginTransaction();
                        fragmentTransaction.replace(R.id.frame,secondfragment);
                        fragmentTransaction.commit();
                    }
                });

MySecondFragment (getting null for savedInstanceState and all bundle agruments!):

@Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
view = inflater.inflate(R.layout.fragment_second, container, false);

        value = getArguments().getString("key");
        id = getArguments().getString("id");
}
Jonathan Scialpi
  • 771
  • 2
  • 11
  • 32

1 Answers1

0

You cannot set arguments on a Fragment after it is attached to an Activity.

Your issue is caused by confusion about Fragment creation. What you provided in your question is not the correct way to send arguments to another Fragment type.

The de-facto standard way of passing arguments to a Fragment when it is created it to use a static factory method, generally called newInstance(). You should set the arguments this way, and should do so before committing the FragmentTransaction - however, you technically could do it right after committing the transaction with no ill effects. This is because when a Fragment is committed, it isn't immediately attached/created, rather, it is queued on the main thread.

Here is how you would do it:

Write a method in your Fragment class called new instance. Be sure to leave a public default (no arguments) constructor for the system to handle things in the background.

public MyFirstFragment extends Fragment {

public MyFirstFragment(){
//constructor - don't use this to create a new fragment directly
}

public static MyFirstFragment newInstance(String argument1, String argument2) {

    // This is where you set the Fragment arguments:

    MyFirstFragment instance = new MyFirstFragment();
    Bundle arguments = new Bundle();

    // add whatever arguments you need to the bundle
    arguments.putString("ARGUMENT_1_KEY", argument1);
    arguments.putString("ARGUMENT_2_KEY", argument2);

    //Set the arguments on the new fragment instance
    instance.setArguments(arguments);

    return instance;
}

// recover the values in onCreate:
@Override
public void onCreate(Bundle savedInstanceState) {

    // an easy way to check if this is a new instance is to null-check the saved state Bundle
    if (savedInstanceState == null) {
        String argument1 = getArguments().getString("ARGUMENT_1_KEY");
        String argument2 = getArguments().getString("ARGUMENT_2_KEY");
    } else {
        // restore whatever you need from savedInstanceState bundle
    }

}

Key point - the arguments are passed into the newInstance() method (these can be whatever you want, as long as the type is allowed). The newInstance() method enforces argument types and also prevents setting them after the fragment is already attached to an activity.

After this, in your Activity.onCreate() method:

protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        String argument1 = "some information";
        String argument2 = "other information";

        MyFirstFragment fragment = MyFirstFragment.newInstance(argument1, argument2);
        FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
        fragmentTransaction.replace(R.id.frame,fragment);
        fragmentTransaction.commit();
}
Community
  • 1
  • 1
Preston Garno
  • 1,175
  • 10
  • 33
  • but my issue is happening in the second fragment. My first fragment replaces itself with the second. And once we switch to the second fragment I think the bundle is getting destroyed. How can I save the data before it is destroyed ? – Jonathan Scialpi Mar 11 '17 at 18:40