title: Android TabLayout Fragment Only Updates After Switching to Specific Fragment
body: <p><strong>Background</strong></p>
  <p>I'm having an issue involving updates to a Fragment in an Android project. The app rolls dice for D&amp;D players. The project employs an API from <a href="https://www.random.org/" rel="nofollow noreferrer">Random.Org</a> to provide for greater entropy in random number generation compared to the Java Math.random method.</p>
  <p>The app displays a Tab Layout with a View Pager which switches between three tabs - one to roll a single die, one to roll a set of dice, and one to show the roll history and log info. Roll Die is in position 0, Roll Set is in position 1, and History is in position 2. View Pager uses a FragmentPagerAdapter.</p>
  <p>History contains two TextViews which I use to display roll results and logging data to ensure connection to the API went well. Data is passed from the RollDie and RollSet fragments to the Main Activity by two interfaces. The interface methods then send the data to the FragmentPagerAdapter, which in turn passes two String ArrayLists to the History fragment via bundle.</p>
  <p><strong>The Problem</strong></p>
  <p>My problem is the History tab only seems to update after the single die roll tab is loaded. When I roll a single die then check the history page, the relevant TextViews display as they should. When I roll a set however, the history page doesn't update until I return to the single die roll tab.</p>
  <p>Any help with this issue would be greatly appreciated. Relevant code posted below.</p>
  <p>Code from the API can be found on <a href="https://github.com/RandomOrg/JSON-RPC-Java" rel="nofollow noreferrer">Github</a>. I have also left out two classes I wrote called Die and DieSet - these work well and I figured this is already long enough. I'm happy to post those classes if anyone thinks it will help.</p>
  <p>Code related to the API key has been omitted along with some IDE generated comments.</p>
  <p><strong>Main Activity</strong></p>
  <pre><code>public class MainActivity extends AppCompatActivity implements DieRollFragment.RollFragmentListener, DieSetFragment.SetFragmentListener{
  
      private static String[] key;
      TabLayout tabLayout;
      ViewPager viewPager;
      PagerAdapter pagerAdapter;
  
      protected void onStart() {
          super.onStart();
          userKeyDialog();
      }
  
      @Override
      protected void onCreate(Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
          setContentView(R.layout.activity_main);
          tabLayout = findViewById(R.id.navTabs);
          viewPager = findViewById(R.id.viewPager);
          pagerAdapter = new PagerAdapter(getSupportFragmentManager(), BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT, tabLayout.getTabCount());
          viewPager.setAdapter(pagerAdapter);
          tabLayout.setupWithViewPager(viewPager);
      }
  
      private void userKeyDialog(){
          //OMITTED FOR PRIVACY REASONS
      }
  
      public static String getKey() {
          //OMITTED FOR PRIVACY REASONS
      }
  
  
      //DieRollFragment Interface Methods
      @Override
      public void rollResultsUpdate(String input) {
          pagerAdapter.setResults(input);
      }
  
      @Override
      public void rollLogsUpdate(String input) {
          pagerAdapter.setLogs(input);
      }
      
      //DieSetFragment Interface Methods
      @Override
      public void setResultsUpdate(String input) {
          pagerAdapter.setResults(input);
      }
  
      @Override
      public void setLogsUpdate(String input) {
          pagerAdapter.setLogs(input);
      }
  }
  </code></pre>
  <p><strong>FragmentPagerAdapter</strong></p>
  <pre><code>public class PagerAdapter extends FragmentPagerAdapter {
  
      int numOfTabs;
      ArrayList&lt;String&gt; results;
      ArrayList&lt;String&gt; logs;
  
      public PagerAdapter(FragmentManager fm, int behavior, int numOfTabs) {
          super(fm, behavior);
          this.numOfTabs = numOfTabs;
          results = new ArrayList&lt;&gt;();
          logs = new ArrayList&lt;&gt;();
      }
  
  
      @NonNull
      @Override
      public Fragment getItem(int position) {
          switch(position){
              case(1):
                  return DieSetFragment.newInstance(getKey());
              case(2):
                  return RollHistoryFragment.newInstance(results, logs);
              case(0):
              default:
                  return DieRollFragment.newInstance(getKey());
          }
      }
  
      @Override
      public CharSequence getPageTitle(int position){
          String title;
          switch(position){
              case(1):
                  title = &quot;Roll Set&quot;;
                  return title;
              case(2):
                  title = &quot;Results&quot;;
                  return title;
              case(0):
              default:
                  title = &quot;Roll Die&quot;;
                  return title;
          }
  
      @Override
      public int getCount() {
          return 3;
      }
  
      public void setResults(String input) {
          results.add(input);
      }
  
      public void setLogs(String input) {
          logs.add(input);
      }
  }
  </code></pre>
  <p><strong>RollHistoryFragment</strong></p>
  <pre><code>public class RollHistoryFragment extends Fragment{
  
      TextView results, logs;
      private static final String ARG_PARAM1 = &quot;param1&quot;;
      private static final String ARG_PARAM2 = &quot;param2&quot;;
      ArrayList&lt;String&gt; inputResults, inputLogs;
      Button clearLogs;
  
      public RollHistoryFragment() {
          // Required empty public constructor
      }
  
      public static RollHistoryFragment newInstance(ArrayList&lt;String&gt; inputResults, ArrayList&lt;String&gt; inputLogs) {
          RollHistoryFragment fragment = new RollHistoryFragment();
          Bundle args = new Bundle();
          args.putStringArrayList(ARG_PARAM1, inputResults);
          args.putStringArrayList(ARG_PARAM2, inputLogs);
          fragment.setArguments(args);
          return fragment;
      }
  
      @Override
      public void onCreate(Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
          if (getArguments() != null) {
              inputResults = getArguments().getStringArrayList(ARG_PARAM1);
              inputLogs = getArguments().getStringArrayList(ARG_PARAM2);
          }
      }
  
      @Override
      public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
          View view = inflater.inflate(R.layout.fragment_roll_history, container, false);
  
          results = view.findViewById(textViewResults);
          results.setMovementMethod(new ScrollingMovementMethod());
          logs = view.findViewById(textViewLogs);
          logs.setMovementMethod(new ScrollingMovementMethod());
  
          clearLogs = view.findViewById(buttonClear);
          clearLogs.setOnClickListener(view1 -&gt; {
              results.setText(&quot;&quot;);
              logs.setText(&quot;&quot;);
          });
  
          updateResults(inputResults);
          updateLogs(inputLogs);
          return view;
      }
  
      public void updateResults(ArrayList&lt;String&gt; input){
          for (String s : input) results.append(s+&quot;\n&quot;);
      }
  
      public void updateLogs (ArrayList&lt;String&gt; input){
          for (String s : input) logs.append(s+&quot;\n&quot;);
      }
  }
  </code></pre>
  <p><strong>DieRollFragment</strong></p>
  <pre><code>public class DieRollFragment extends Fragment {
  
      private static final String ARG_PARAM1 = &quot;param1&quot;;
      private String key;
      private RollFragmentListener listener;
  
      public DieRollFragment() {
          // Required empty public constructor
      }
  
      public static DieRollFragment newInstance(String key){
          DieRollFragment fragment = new DieRollFragment();
          Bundle args = new Bundle();
          args.putString(ARG_PARAM1, key);
          fragment.setArguments(args);
          return fragment;
      }
  
      @Override
      public void onCreate(Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
          if (getArguments() != null) {
              key = getArguments().getString(ARG_PARAM1);
          }
      }
  
      @Override
      public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
          // Inflate the layout for this fragment
          View view = inflater.inflate(R.layout.fragment_die_roll, container, false);
          ImageButton rollD4 = view.findViewById(R.id.rollD4);
          ImageButton rollD6 = view.findViewById(R.id.rollD6);
          ImageButton rollD8 = view.findViewById(R.id.rollD8);
          ImageButton rollD10 = view.findViewById(R.id.rollD10);
          ImageButton rollD12 = view.findViewById(R.id.rollD12);
          ImageButton rollD20 = view.findViewById(R.id.rollD20);
          ImageButton rollD100 = view.findViewById(R.id.rollD100);
  
          rollD4.setOnClickListener(view1 -&gt; {
              Die d4 = new Die(4, key);
              int result = d4.makeRoll();
              showAlert(result);
              listener.rollResultsUpdate(&quot;Roll = &quot; + result);
              listener.rollLogsUpdate(d4.getLog());
          });
  
          rollD6.setOnClickListener(view12 -&gt; {
              Die d6 = new Die(6, key);
              int result = d6.makeRoll();
              showAlert(result);
              listener.rollResultsUpdate(&quot;Roll = &quot; + result);
              listener.rollLogsUpdate(d6.getLog());
          });
  
          rollD8.setOnClickListener(view13 -&gt; {
              Die d8 = new Die(8, key);
              int result = d8.makeRoll();
              showAlert(result);
              listener.rollResultsUpdate(&quot;Roll = &quot; + result);
              listener.rollLogsUpdate(d8.getLog());
          });
  
          rollD10.setOnClickListener(view14 -&gt; {
              Die d10 = new Die(10, key);
              int result = d10.makeRoll();
              showAlert(result);
              listener.rollResultsUpdate(&quot;Roll = &quot; + result);
              listener.rollLogsUpdate(d10.getLog());
          });
  
          rollD12.setOnClickListener(view15 -&gt; {
              Die d12 = new Die(12, key);
              int result = d12.makeRoll();
              showAlert(result);
              listener.rollResultsUpdate(&quot;Roll = &quot; + result);
              listener.rollLogsUpdate(d12.getLog());
          });
  
          rollD20.setOnClickListener(view16 -&gt; {
              Die d20 = new Die(20, key);
              int result = d20.makeRoll();
              showAlert(result);
              listener.rollResultsUpdate(&quot;Roll = &quot; + result);
              listener.rollLogsUpdate(d20.getLog());
          });
  
          rollD100.setOnClickListener(view17 -&gt; {
              Die d100 = new Die(100, key);
              int result = d100.makeRoll();
              showAlert(result);
              listener.rollResultsUpdate(&quot;Roll = &quot; + result);
              listener.rollLogsUpdate(d100.getLog());
          });
          return view;
      }
  
      public interface RollFragmentListener{
          void rollResultsUpdate(String input);
          void rollLogsUpdate(String input);
      }
  
      private void showAlert(int result){
          new AlertDialog.Builder(Objects.requireNonNull(getContext()))
                  .setTitle(&quot;You rolled a: &quot;)
                  .setMessage(Integer.toString(result))
                  .show();
      }
  
      public void onAttach(@NonNull Context context) {
          super.onAttach(context);
          if(context instanceof RollFragmentListener){
              listener = (RollFragmentListener) getContext();
          } else throw new RuntimeException(context.toString() + &quot; must implement RollFragmentListener&quot;);
      }
      @Override
      public void onDetach() {
          super.onDetach();
          listener = null;
      }
  }
  </code></pre>
  <p><strong>DieSetFragment</strong></p>
  <pre><code>    public DieSetFragment() {
          // Required empty public constructor
      }
  
      public static DieSetFragment newInstance(String key) {
          DieSetFragment fragment = new DieSetFragment();
          Bundle args = new Bundle();
          args.putString(ARG_PARAM1, key);
          fragment.setArguments(args);
          return fragment;
      }
  
      @Override
      public void onCreate(Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
          if (getArguments() != null) {
              mParam1 = getArguments().getString(ARG_PARAM1);
          }
  
      }
  
      @Override
      public View onCreateView(LayoutInflater inflater, ViewGroup container,
                               Bundle savedInstanceState) {
          // Inflate the layout for this fragment
          View view = inflater.inflate(R.layout.fragment_die_set, container, false);
          assert container != null;
          editNumD4 = view.findViewById(R.id.editNumD4);
          editNumD6 = view.findViewById(R.id.editNumD6);
          editNumD8 = view.findViewById(R.id.editNumD8);
          editNumD10 = view.findViewById(R.id.editNumD10);
          editNumD12 = view.findViewById(R.id.editNumD12);
          editNumD20 = view.findViewById(R.id.editNumD20);
          diceSetList = new ArrayList&lt;&gt;();
  
          ImageButton buttonRollSet = view.findViewById(R.id.buttonRollSet);
          buttonRollSet.setOnClickListener(view1 -&gt; rollSet(mParam1));
  
          return view;
      }
  
      public interface SetFragmentListener{
          void setResultsUpdate(String input);
          void setLogsUpdate(String input);
      }
  
      public void rollSet(String key){
          int numD4 = Integer.parseInt(editNumD4.getText().toString());
          int numD6 = Integer.parseInt(editNumD6.getText().toString());
          int numD8 = Integer.parseInt(editNumD8.getText().toString());
          int numD10 = Integer.parseInt(editNumD10.getText().toString());
          int numD12 = Integer.parseInt(editNumD12.getText().toString());
          int numD20 = Integer.parseInt(editNumD20.getText().toString());
  
          for(int i = 0; i&lt;numD4; i++){
              Die d4 = new Die(4,key);
              diceSetList.add(d4);
          }
          for(int i = 0; i&lt;numD6; i++){
              Die d6 = new Die(6,key);
              diceSetList.add(d6);
          }
          for(int i = 0; i&lt;numD8; i++){
              Die d8 = new Die(8,key);
              diceSetList.add(d8);
          }
          for(int i = 0; i&lt;numD10; i++){
              Die d10 = new Die(10,key);
              diceSetList.add(d10);
          }
          for(int i = 0; i&lt;numD12; i++){
              Die d12 = new Die(12,key);
              diceSetList.add(d12);
          }
          for(int i = 0; i&lt;numD20; i++){
              Die d20 = new Die(20,key);
              diceSetList.add(d20);
          }
  
          DieSet dieSet = new DieSet(diceSetList,key);
          int result = dieSet.rollTotal();
          listener.setLogsUpdate(dieSet.getLOG());
          listener.setResultsUpdate(&quot;Set Roll = &quot; + result);
          showAlert(result);
          diceSetList.clear();
      }
  
      public void showAlert(int result){
          new AlertDialog.Builder(Objects.requireNonNull(getContext()))
                  .setTitle(&quot;You rolled a: &quot;)
                  .setMessage(Integer.toString(result))
                  .show();
      }
  
      public void onAttach(@NonNull Context context) {
          super.onAttach(context);
          if(context instanceof SetFragmentListener){
              listener = (SetFragmentListener) getContext();
          } else throw new RuntimeException(context.toString() + &quot;must implement SetFragmentListener&quot;);
      }
  
      @Override
      public void onDetach() {
          super.onDetach();
          listener = null;
      }
  }
  </code></pre>