0

In my app, I have multiple instances of the same fragment, ActivityFragment. In each fragment, there is an activity_text textview. When the fragment is added to the layout, I want to set the activity_text textview within that fragment during onCreate. However, when I try to do this, every ActivityFragment onscreen will have their activity_text textview changed.

Is there any way that I can limit setText to within the scope of an individual fragment without using unique Tags or IDs for each fragment?

Here is my ActivityFragment class:

public static class ActivityFragment extends Fragment {
    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable final ViewGroup container, Bundle savedInstanceState) {
        final View fragment1 = inflater.inflate(R.layout.activity_fragment, container, false);

        final TextView activityText = (TextView) fragment1.findViewById(R.id.activity_text);
        //Calling setText changes the activityText Textview in every fragment onscreen
        activityText.setText(text);


        return fragment1;
    }
}

Here is my MainActivity class:

public class MainActivity extends FragmentActivity {
    Static String text;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        for (int i = 0; i != 5; i++) {
            //This ensures each fragment receives a unique String
            text = "success" + i;
            ActivityFragment myFragment = new ActivityFragment();
            getFragmentManager().beginTransaction()
                    .add(R.id.fragment_container, myFragment).commit();
        }
    }
}    
Ewen Crawford
  • 89
  • 2
  • 8
  • Can you be more specific on your question? What exactly do mean by " limit setText to within the scope of an individual fragment"? You can override methods like **onAttach** on **onDetach** do deal with the moment that the fragment gets attached. You can also **send data through bundle** for each fragment. Is that what you want? – Victor Hugo Montes Nov 02 '17 at 22:08
  • @VictorNeves As per the answers provided, I should be passing data to the fragment through a Bundle. Sorry for the confusing question. – Ewen Crawford Nov 02 '17 at 23:23

2 Answers2

1

It looks like there's two problems with your code.

The first is that you're using a static String text to transmit information from your Activity to your Fragments. In general, this is not a good idea; if you need to "pass" something from your Activity to your Fragment at the time it's constructed, you should use Fragment.setArguments(Bundle) to do that.

The second is that you seem to have a misconception about the timing of FragmentTransactions. Your for loop changes the value of text and then .commit()s a new fragment five times. But these transactions are asynchronous, and the fragment lifecycle has its own timeline. So your onCreateView() will actually wind up being called after your activity onCreate() has finished, and so each of your five fragments gets the same value from text.

Here's how I'd solve it:

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        for (int i = 0; i != 5; i++) {
            Bundle args = new Bundle();
            args.putString("text", "success" + i);

            ActivityFragment myFragment = new ActivityFragment();
            myFragment.setArguments(args);

            getFragmentManager().beginTransaction()
                                .add(R.id.fragment_container, myFragment).commit();
        }
    }

    public static class ActivityFragment extends Fragment {
        @Nullable
        @Override
        public View onCreateView(LayoutInflater inflater, @Nullable final ViewGroup container, Bundle savedInstanceState) {
            final View fragment1 = inflater.inflate(R.layout.activity_fragment, container, false);

            final TextView activityText = (TextView) fragment1.findViewById(R.id.activity_text);
            String text = getArguments().getString("text");
            activityText.setText(text);

            return fragment1;
        }
    }
}
Ben P.
  • 52,661
  • 6
  • 95
  • 123
1

Your issue have nothing to do with the scope of the textview. Each fragment is individually setting the textView to text, as you instructed them to do so. That happens because onCreateView gets called much latter, after all the fragment transactions happened.

On your code you put the comment: //This ensures each fragment receives a unique String, actually, there's nothing there ensuring that fragments are receiving anything. I recommend you reading what a static means in Java. On that for-loop you change the value of text 5 times in a row and the last value is "success4".

The correct way to pass parameters to a fragment is via a Bundle added calling the methong setArguments(Bundle)

I searched and this answer here https://stackoverflow.com/a/35737232/906362 shows very well explained how to do that. The gist is something like this:

    for (int i = 0; i != 5; i++) {
        ActivityFragment myFragment = new ActivityFragment();
        Bundle b = new Bundle();
        // This really ensures each fragment receives a unique String
        b.putString("text", "success" + i)
        myFragment.setArguments(b);
        getFragmentManager().beginTransaction()
                .add(R.id.fragment_container, myFragment).commit();
    }

and then to get this value on the fragment:

  TextView activityText = (TextView) fragment1.findViewById(R.id.activity_text);
  activityText.setText(getArguments().getString("text");
Budius
  • 39,391
  • 16
  • 102
  • 144