title: Avoid getting Race condition in Android Volley in Android app
body: <p>I'm new to <code>Android Development</code> and I'm trying to develop my first Android app which gets data from some <code>public APIs</code> using <code>Android Volley</code>.</p>
  
  <p>I'm using <code>singleton Volley Request Queue</code> which is initialized in the launcher activity. I am successfully able to parse the JSON contents and display them on a <code>Fragment layout/view (uses RecyclerView &amp; CardView)</code> when I set my <code>RecyclerView</code> adapters INSIDE the <code>Volley's JsonObjectRequest</code>. </p>
  
  <p>The following code does display data, but suffers from time race condition.
  Note: RvJoiner is a library which merges multiple adapters and makes a single adapter ordered by FIRST COME FIRST SERVE basis.</p>
  
  <p>My Fragment class is as follows:</p>
  
  <pre><code>public class Fragment1 extends Fragment {
  
  @Override
  public View onCreateView(LayoutInflater inflater, ViewGroup container,
                           Bundle savedInstanceState) {
      View v = inflater.inflate(R.layout.recylcer_main, container, false);
      ParseJSON parseJSON = new ParseJSON(v);
      parseJSON.makeRequest1();
      parseJSON.makeRequest2();
  
      return v;
     }
  }
  </code></pre>
  
  <p>My ParseJSON class is as follows</p>
  
  <pre><code>public class ParseJSON {
  
  private static final String URL1 = "some url";
  private static final String URL2 = "some other url";
  private static final String TAG = "ParseJSON";
  private RequestQueue requestQueue;
  
  private boolean FLAG_REQUEST1_FETCHED;
  private boolean FLAG_REQUEST2_FETCHED;
  
  private ArrayList&lt;status1&gt; status1ArrayList;
  private ArrayList&lt;status2&gt; status2ArrayList;
  
  private Context context;
  private RvJoiner rvJoiner;
  private View view;
  
  ProgressDialog pd;
  
  ParseJSON (View v){
      this.view= v;
      this.context=v.getContext();
      pd = ProgressDialog.show(v.getContext(), "Please Wait", "Getting Data from APIs", true);
      requestQueue = AppController.getInstance(v.getContext()).getRequestQueue();
      rvJoiner = new RvJoiner();
  }
  
  
  public void makeRequest1() {
      JsonObjectRequest request1 = new JsonObjectRequest(Request.Method.GET, URL1,
              null, new Response.Listener&lt;JSONObject&gt;() {
          @Override
          public void onResponse(JSONObject response) {
  
              try {
                  /* Parsing Stuff and storing it in status1ArrayList */ 
  
          FLAG_REQUEST1_FETCHED=true;
  
                      Status1Adapter status1Adapter = new Status1Adapter(status1ArrayList);
                      RecyclerView recList = (RecyclerView) view.findViewById(R.id.cardList);
                      recList.setLayoutManager(new LinearLayoutManager(context));
  
                      rvJoiner.add(new JoinableAdapter(status1Adapter));
                      recList.setAdapter(rvJoiner.getAdapter());
                      pd.dismiss();
                  }
  
              } catch (JSONException e) {}
          }
  
      }, new Response.ErrorListener() {
          @Override
          public void onErrorResponse(VolleyError error) {}
      });
      AppController.getInstance(context).addToRequestQueue(request1);
  }
  
  public void makeRequest2() {
  
      JsonObjectRequest request2 = new JsonObjectRequest(Request.Method.GET, URL2,
              null, new Response.Listener&lt;JSONObject&gt;() {
          @Override
          public void onResponse(JSONObject response) {
              try {
          /* Parsing stuff and storing it inside ArrayList status2ArrayList */
  
  FLAG_REQUEST2_FETCHED=true;
  
                      Status2Adapter status2Adapter = new Staus2Adapter(status2ArrayList);
  
                      RecyclerView recList = (RecyclerView) view.findViewById(R.id.cardList);
                      recList.setLayoutManager(new LinearLayoutManager(context));
  
                      rvJoiner.add(new JoinableAdapter(status2Adapter));
                  }
  
              } catch (JSONException e) {}
          }
  
      }, new Response.ErrorListener() {
          @Override
          public void onErrorResponse(VolleyError error) {}
      });
      AppController.getInstance(context).addToRequestQueue(request2);
  }
  
  public boolean isStatusFetched(){
      return FLAG_REQUEST1_FETCHED &amp;&amp; FLAG_REQUEST2_FETCHED;
  }
  
  public ArrayList&lt;status1&gt; getstatus1ArrayList() {
      return status1ArrayList;
  }
  
  
  public ArrayList&lt;status2&gt; getstatus2ArrayList() {
      return status2ArrayList;
  }
  }
  </code></pre>
  
  <p>In the above code, I'm having a race condition. Since <code>Volley</code> network calls are asynchronous in nature, I have no control on which request will get completed and displayed on my <code>Fragment CardView</code> first. (i.e any of <code>rvJoiner.add()</code> requests can be executed first)</p>
  
  <p>I would like to make my UI consistent i.e I want Request1 adapter to be added to RvJoiner first and then the Request2.</p>
  
  <p>If possible, I would like to move all my code that sets adapters and joins them from JsonObjectRequest to my Fragment's onCreateView method. So, in this way, I have a control on the order of adapters. However, then I need a method which checks the value of <code>FLAG_REQUEST1_FETCHED</code> and <code>FLAG_REQUEST2_FETCHED</code> via <code>isStatusFetched</code> method continuously.</p>
  
  <p>Code for the Fragment class will be</p>
  
  <pre><code>public class Fragment1 extends Fragment {
  
  @Override
  public View onCreateView(LayoutInflater inflater, ViewGroup container,
                           Bundle savedInstanceState) {
      View v = inflater.inflate(R.layout.recylcer_main, container, false);
      ParseJSON parseJSON = new ParseJSON(v);
      parseJSON.makeRequest1();
      parseJSON.makeRequest2();
  
  while(!parseJSON.isDataFetched()){
  /* I want to wait here till both status1ArrayList and status2ArrayList gets     populated with data in ParseJSON. In this way I can control the order in which adapters are added inside RvJoiner. If I don't wait here I will get NullPointerException on runtime since Volley calls are asynchronous and getStatus1ArrayList/getStatus2ArrayList will most probably return null. But how to wait here without consuming too much CPU power? */
  }
  
      ArrayList&lt;status1&gt; status1ArrayList = parseJSON.getstatus1ArrayList();
      ArrayList&lt;status2&gt; status2ArrayList = parseJSON.getstatus2ArrayList();  
  
      Status1Adapter status1Adapter = new Status1Adapter(status1ArrayList);
      Status2Adapter status2Adapter = new Status2Adapter(status2ArrayList);
  
      RecyclerView recList = (RecyclerView) v.findViewById(R.id.cardList);
      recList.setLayoutManager(new LinearLayoutManager(v.getContext()));
  
  RvJoiner rvJoiner = new RvJoiner();
  /* Problem solved as I'm adding adapters in the order I want */
      rvJoiner.add(new JoinableAdapter(status1Adapter)); 
      rvJoiner.add(new JoinableAdapter(status2Adapter));
  
      recList.setAdapter(rvJoiner.getAdapter());
      return v;
  }
  
  }
  </code></pre>
  
  <p>One solution can be using callbacks. I read somewhere about them, but I'm not sure if it solves my problem of 'multiple request at the same time while maintaining order'.</p>
  
  <p>Another solution would be to restrict my Volley Queue to handle one request at one time only but that would increase the time taken to fetch and serve data. This is my last choice.</p>
  
  <p>I am virtually out of ideas and would like someone to help me so that I can control the order of setting my adapters and maintain a consistent UI. If you need any other information, please tell me.</p>
  
  <p>Thanks.</p>