Country, state and city spinner not working correctly
<p>I've been working on a registration form app with few spinner widgets being used in it. The spinners are to be used to select <strong>Country</strong>, <strong>State</strong> and <strong>City</strong>. Hence, these spinners need to be interconnected somehow (The code below would show how I have tried to achieve that).</p>

<p>Form code:</p>

<h3>fragment_register.xml</h3>

<pre><code>&lt;?xml version="1.0" encoding="utf-8"?&gt;

&lt;ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fillViewport="true"&gt;

&lt;LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_marginLeft="40dp"
android:layout_marginRight="40dp"
android:gravity="center"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:nestedScrollingEnabled="true"&gt;


&lt;TextView
    android:text="Student Registration Form"
    android:textSize="22sp"
    android:textAlignment="center"
    android:layout_marginBottom="20dp"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content" /&gt;

    &lt;Spinner
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/country_spinner"
        android:foregroundTint="#222"
        android:background="#001c47"
        android:layout_marginBottom="20dp" /&gt;

    &lt;Spinner
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/state_spinner"
        android:foregroundTint="#222"
        android:background="#001c47"
        android:layout_marginBottom="20dp" /&gt;

    &lt;Spinner
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/city_spinner"
        android:foregroundTint="#222"
        android:background="#001c47"
        android:layout_marginBottom="20dp" /&gt;

&lt;/LinearLayout&gt;
&lt;/ScrollView&gt;
</code></pre>

<p>The code above has more widgets which you might find in the java file; I haven't included them in above code as it would make it too long.</p>

<h3>RegisterFragement.java</h3>

<pre><code>import android.app.Fragment;
import android.app.FragmentTransaction;
import android.content.SharedPreferences;
import android.nfc.Tag;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;


import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.TextView;

import com.android.volley.RequestQueue;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.StringRequest;
import com.android.volley.toolbox.Volley;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.util.ArrayList;
import android.support.design.widget.Snackbar;
import android.support.v7.widget.AppCompatButton;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.EditText;
import android.widget.ProgressBar;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;


public class RegisterFragment extends Fragment  implements View.OnClickListener, Spinner.OnItemSelectedListener{

private AppCompatButton btn_register;
private EditText et_email,et_password,et_name;
private TextView tv_login;
private ProgressBar progress;
//Declaring the Spinners
private Spinner country_spinner;
private Spinner state_spinner;
private Spinner city_spinner;


//An ArrayList for Spinner Items
private ArrayList&lt;String&gt; results;
// countGetData: It will keep a count of how many times get data has been run and for 0 times
// it would set the spinners to default state
private int countGetData;
ArrayList student1 = new ArrayList();


//JSON Array
private JSONArray resultArray;


@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

    View view = inflater.inflate(R.layout.fragment_register,container,false);
    initViews(view);
    return view;

}

private void initViews(View view){

    btn_register = (AppCompatButton)view.findViewById(R.id.btn_register);
    tv_login = (TextView)view.findViewById(R.id.tv_login);
    et_name = (EditText)view.findViewById(R.id.et_name);
    et_email = (EditText)view.findViewById(R.id.et_email);
    et_password = (EditText)view.findViewById(R.id.et_password);

    progress = (ProgressBar)view.findViewById(R.id.progress);

    btn_register.setOnClickListener(this);
    tv_login.setOnClickListener(this);
    //Initializing the ArrayList
    results = new ArrayList&lt;String&gt;();
    // Initializing countGetData
    countGetData = 0;

    //Initializing Spinner
    country_spinner = (Spinner) view.findViewById(R.id.country_spinner);
    state_spinner = (Spinner) view.findViewById(R.id.state_spinner);
    city_spinner = (Spinner) view.findViewById(R.id.city_spinner);


    //Adding an Item Selected Listener to our Spinner
    //As we have implemented the class Spinner.OnItemSelectedListener to this class iteself we are passing this to setOnItemSelectedListener
    country_spinner.setOnItemSelectedListener(this);
    state_spinner.setOnItemSelectedListener(this);
    city_spinner.setOnItemSelectedListener(this);
    university_spinner.setOnItemSelectedListener(this);
    college_spinner.setOnItemSelectedListener(this);
    ca_spinner.setOnItemSelectedListener(this);


    getData("getCountries", "", 0);
}


@Override
public void onClick(View v) {

    switch (v.getId()){
        case R.id.tv_login:
            goToLogin();
            break;

        case R.id.btn_register:

            String name = et_name.getText().toString();
            String email = et_email.getText().toString();
            String password = et_password.getText().toString();

            if(!name.isEmpty() &amp;&amp; !email.isEmpty() &amp;&amp; !password.isEmpty()) {

                progress.setVisibility(View.VISIBLE);
                registerProcess(name,email,password);

            } else {

                Snackbar.make(getView(), "Fields are empty !", Snackbar.LENGTH_LONG).show();
            }
            break;

    }

}

private void getData(String urlPart1,String urlPart2, long itemId) {
    //Creating a string request
    StringRequest stringRequest = new StringRequest(Config.DATA_URL+urlPart1+"&amp;"+urlPart2+"="+itemId,
            new Response.Listener&lt;String&gt;() {
                @Override
                public void onResponse(String response) {
                    JSONObject j = null;
                    try {
                        //Parsing the fetched Json String to JSON Object
                        j = new JSONObject(response);

                        //Storing the Array of JSON String to our JSON Array
                        resultArray = j.getJSONArray(Config.JSON_ARRAY);

                        //Calling method getStudents to get the students from the JSON Array
                        getResults(resultArray);

                    } catch (JSONException e) {
                        e.printStackTrace();
                    }
                }
            },
            new Response.ErrorListener() {
                @Override
                public void onErrorResponse(VolleyError error) {

                }
            });

//Creating a request queue
        RequestQueue requestQueue = Volley.newRequestQueue(getActivity().getApplicationContext());
    //Adding request to the queue
    requestQueue.add(stringRequest);

}

private void getResults(JSONArray j) {
    //Traversing through all the items in the json array
    for (int i = 0; i &lt; j.length(); i++) {
        try {
            //Getting json object
            JSONObject json = j.getJSONObject(i);

            //Adding the name of the student to array list
            results.add(json.getString(Config.TAG_NAME));
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    if(countGetData == 0) {
        student1.add("Select This");
        //Setting adapter to show the items in the spinner
        country_spinner.setAdapter(new ArrayAdapter&lt;String&gt;(getActivity().getApplicationContext(), android.R.layout.simple_spinner_dropdown_item, results));
        state_spinner.setAdapter(new ArrayAdapter&lt;String&gt;(getActivity().getApplicationContext(), android.R.layout.simple_spinner_dropdown_item, student1));
        city_spinner.setAdapter(new ArrayAdapter&lt;String&gt;(getActivity().getApplicationContext(), android.R.layout.simple_spinner_dropdown_item, student1));
        countGetData += 1;
    }
}



//this method will execute when we pic an item from the spinner
@Override
public void onItemSelected(AdapterView&lt;?&gt; parent, View view, int position, long id) {

    if(country_spinner.getSelectedItem().toString().equals("Austria")){
        long itemId = country_spinner.getSelectedItemId();
        getData("getStates","countryId",itemId);
        state_spinner.setAdapter(new ArrayAdapter&lt;String&gt;(getActivity().getApplicationContext(), android.R.layout.simple_spinner_dropdown_item, results));
    }
    else{
        long itemId = country_spinner.getSelectedItemId();
        getData("getStates","countryId",itemId);
        state_spinner.setAdapter(new ArrayAdapter&lt;String&gt;(getActivity().getApplicationContext(), android.R.layout.simple_spinner_dropdown_item, results));
    }


}
}
</code></pre>

<p>There is a PHP API which returns the json for Country, State or City based on the url. For ex.:
    <code>http://www.example.com/location_api/api.php?type=getCountries
http://www.example.com/location_api/api.php?type=getStates&amp;countryId=12
http://www.example.com/location_api/api.php?type=getCities&amp;stateId=1</code></p>

<p>In <strong>onItemSelected</strong> I'm trying to dynamically set spinners with respect to the previous spinner. For ex., I'm setting the <strong>state</strong> spinner whenever a <strong>country</strong> spinner item is selected. I'm checking this through a <strong>if-else</strong> block; if condition checks if <strong>Austria</strong>(one of the countries in the list; random choice) is selected then set the <strong>state</strong> spinner <strong>else</strong> also set the <strong>state</strong> spinner. This way I end up setting the state spinner according to the country spinner element.</p>

<p>To specify to the API which <strong>country</strong> is being chosen I'm using the itemId which contains the Id of the selected item in country spinner.
<code>long itemId = country_spinner.getSelectedItemId();</code></p>

<p>Then when I have the Id I call the <strong>getData</strong> method which sets the <strong>result</strong> ArraryList and I assign it to the spinner <strong>state</strong>.</p>

<p><code>getData("getStates","countryId",itemId);
state_spinner.setAdapter(new ArrayAdapter&lt;String&gt;(getActivity().getApplicationContext(), android.R.layout.simple_spinner_dropdown_item, results));</code></p>

<p>The above code is making the app crash at run time with following error(only part of it which I think might be useful, full Logcat file here: <a href="http://pastebin.com/Wvz4udtG">Link</a>):</p>

<blockquote>
  <p>--------- beginning of crash 04-13 21:05:09.782 9288-9600/com.gouravchawla.loginregistration E/AndroidRuntime: FATAL
  EXCEPTION: Thread-503
                                                                                   Process: com.gouravchawla.loginregistration, PID: 9288
                                                                                   java.lang.NegativeArraySizeException: -110
                                                                                       at
  com.android.volley.toolbox.DiskBasedCache.streamToBytes(DiskBasedCache.java:316)
                                                                                       at
  com.android.volley.toolbox.DiskBasedCache.get(DiskBasedCache.java:117)
                                                                                       at com.android.volley.CacheDispatcher.run(CacheDispatcher.java:101)</p>
  
  <p>Throwing OutOfMemoryError "Failed to allocate a 1667853436 byte
  allocation with 777786 free bytes and 381MB until OOM"</p>
</blockquote>