Country, state, and city meters are not working properly

I am working on a registration form application with several widgets that are used in it. To use Country , State and City . Therefore, these spinners must be somehow related to each other (the code below will show how I tried to achieve this).

Form Code:

fragment_register.xml

<?xml version="1.0" encoding="utf-8"?> <ScrollView xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:fillViewport="true"> <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"> <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" /> <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" /> <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" /> <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" /> </LinearLayout> </ScrollView> 

In the above code, there are more widgets that you can find in the java file; I have not included them in the code above, as it is too long.

RegisterFragement.java

 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<String> 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<String>(); // 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() && !email.isEmpty() && !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+"&"+urlPart2+"="+itemId, new Response.Listener<String>() { @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 < 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<String>(getActivity().getApplicationContext(), android.R.layout.simple_spinner_dropdown_item, results)); state_spinner.setAdapter(new ArrayAdapter<String>(getActivity().getApplicationContext(), android.R.layout.simple_spinner_dropdown_item, student1)); city_spinner.setAdapter(new ArrayAdapter<String>(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<?> 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<String>(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<String>(getActivity().getApplicationContext(), android.R.layout.simple_spinner_dropdown_item, results)); } } } 

There is a PHP API that returns json for a country, state, or city based on the URL. For example: http://www.example.com/location_api/api.php?type=getCountries http://www.example.com/location_api/api.php?type=getStates&countryId=12 http://www.example.com/location_api/api.php?type=getCities&stateId=1

In onItemSelected I am trying to dynamically set the spinners relative to the previous counter. For example, I set a state counter whenever a country element is selected. I check this through the if-else block; if the condition checks if Austria is selected (one of the countries in the list, random selection), then set the state to spinner else, also set the value to state . So I end up setting up the status counter according to the country counter element.

To indicate the API that the country is selected, I use itemId, which contains the ID of the selected item in the counter country. long itemId = country_spinner.getSelectedItemId();

Then, when I have Id, I call the getData strong> method , which sets the ArrayList result , and I assign it to the spinner state .

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

The above code causes the application to crash at runtime with the following error (only part of it, which in my opinion may be useful, the full Logcat file is here: Link )

--------- start of the crash 04-13 21: 05: 09.782 9288-9600 / com.gouravchawla.loginregistration E / AndroidRuntime: FATAL EXCLUSION: Thread-503 Process: com.gouravchawla.loginregistration, PID: 9288 java .lang.NegativeArraySizeException: -110 in com.android.volley.toolbox.DiskBasedCache.streamToBytes (DiskBasedCache.java data16) in com.android.volley.toolbox.DiskBasedCache.get (DiskBasedCache.java:117) on com.android. volley.CacheDispatcher.run (CacheDispatcher.java:101)

Throwing OutOfMemoryError "Failed to allocate 1667853436 bytes allocation with 777786 free bytes and 381 MB to OOM"

+5
source share
3 answers

in your code you will need to change the counter adapter, which depends, for example, on other spinners.

Changing the spinner city ​​adapter depending on the spinner state adapter as well as changing the spinner state adapter depending on the spinner country adapter,

I wrote an example code that would demonstrate how this can be achieved. I wrote a general code that others can understand when reading the answer, feel free to suggest and modify it, as it meets your requirements.

The code is also available on Github , and another example that will help you download JSON data from your network, OkHttp , GSON and apache-common-io , code

 public class SpinnerCountryActivity extends AppCompatActivity { private Spinner country_Spinner; private Spinner state_Spinner; private Spinner city_Spinner; private ArrayAdapter<Country> countryArrayAdapter; private ArrayAdapter<State> stateArrayAdapter; private ArrayAdapter<City> cityArrayAdapter; private ArrayList<Country> countries; private ArrayList<State> states; private ArrayList<City> cities; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_spinner_country); initializeUI(); } private void initializeUI() { country_Spinner = (Spinner) findViewById(R.id.SpinnerCountryActivity_country_spinner); state_Spinner = (Spinner) findViewById(R.id.SpinnerCountryActivity_state_spinner); city_Spinner = (Spinner) findViewById(R.id.SpinnerCountryActivity_city_spinner); countries = new ArrayList<>(); states = new ArrayList<>(); cities = new ArrayList<>(); createLists(); countryArrayAdapter = new ArrayAdapter<Country>(getApplicationContext(), R.layout.simple_spinner_dropdown_item, countries); countryArrayAdapter.setDropDownViewResource(R.layout.simple_spinner_dropdown_item); country_Spinner.setAdapter(countryArrayAdapter); stateArrayAdapter = new ArrayAdapter<State>(getApplicationContext(), R.layout.simple_spinner_dropdown_item, states); stateArrayAdapter.setDropDownViewResource(R.layout.simple_spinner_dropdown_item); state_Spinner.setAdapter(stateArrayAdapter); cityArrayAdapter = new ArrayAdapter<City>(getApplicationContext(), R.layout.simple_spinner_dropdown_item, cities); cityArrayAdapter.setDropDownViewResource(R.layout.simple_spinner_dropdown_item); city_Spinner.setAdapter(cityArrayAdapter); country_Spinner.setOnItemSelectedListener(country_listener); state_Spinner.setOnItemSelectedListener(state_listener); city_Spinner.setOnItemSelectedListener(city_listener); } private AdapterView.OnItemSelectedListener country_listener = new AdapterView.OnItemSelectedListener() { @Override public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { if (position > 0) { final Country country = (Country) country_Spinner.getItemAtPosition(position); Log.d("SpinnerCountry", "onItemSelected: country: "+country.getCountryID()); ArrayList<State> tempStates = new ArrayList<>(); tempStates.add(new State(0, new Country(0, "Choose a Country"), "Choose a State")); for (State singleState : states) { if (singleState.getCountry().getCountryID() == country.getCountryID()) { tempStates.add(singleState); } } stateArrayAdapter = new ArrayAdapter<State>(getApplicationContext(), R.layout.simple_spinner_dropdown_item, tempStates); stateArrayAdapter.setDropDownViewResource(R.layout.simple_spinner_dropdown_item); state_Spinner.setAdapter(stateArrayAdapter); } cityArrayAdapter = new ArrayAdapter<City>(getApplicationContext(), R.layout.simple_spinner_dropdown_item, new ArrayList<City>()); cityArrayAdapter.setDropDownViewResource(R.layout.simple_spinner_dropdown_item); city_Spinner.setAdapter(cityArrayAdapter); } @Override public void onNothingSelected(AdapterView<?> parent) { } }; private AdapterView.OnItemSelectedListener state_listener = new AdapterView.OnItemSelectedListener() { @Override public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { if (position > 0) { final State state = (State) state_Spinner.getItemAtPosition(position); Log.d("SpinnerCountry", "onItemSelected: state: "+state.getStateID()); ArrayList<City> tempCities = new ArrayList<>(); Country country = new Country(0, "Choose a Country"); State firstState = new State(0, country, "Choose a State"); tempCities.add(new City(0, country, firstState, "Choose a City")); for (City singleCity : cities) { if (singleCity.getState().getStateID() == state.getStateID()) { tempCities.add(singleCity); } } cityArrayAdapter = new ArrayAdapter<City>(getApplicationContext(), R.layout.simple_spinner_dropdown_item, tempCities); cityArrayAdapter.setDropDownViewResource(R.layout.simple_spinner_dropdown_item); city_Spinner.setAdapter(cityArrayAdapter); } } @Override public void onNothingSelected(AdapterView<?> parent) { } }; private AdapterView.OnItemSelectedListener city_listener = new AdapterView.OnItemSelectedListener() { @Override public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { } @Override public void onNothingSelected(AdapterView<?> parent) { } }; private void createLists() { Country country0 = new Country(0, "Choose a Country"); Country country1 = new Country(1, "Country1"); Country country2 = new Country(2, "Country2"); countries.add(new Country(0, "Choose a Country")); countries.add(new Country(1, "Country1")); countries.add(new Country(2, "Country2")); State state0 = new State(0, country0, "Choose a Country"); State state1 = new State(1, country1, "state1"); State state2 = new State(2, country1, "state2"); State state3 = new State(3, country2, "state3"); State state4 = new State(4, country2, "state4"); states.add(state0); states.add(state1); states.add(state2); states.add(state3); states.add(state4); cities.add(new City(0, country0, state0, "Choose a City")); cities.add(new City(1, country1, state1, "City1")); cities.add(new City(2, country1, state1, "City2")); cities.add(new City(3, country1, state2, "City3")); cities.add(new City(4, country2, state2, "City4")); cities.add(new City(5, country2, state3, "City5")); cities.add(new City(6, country2, state3, "City6")); cities.add(new City(7, country2, state4, "City7")); cities.add(new City(8, country1, state4, "City8")); } private class Country implements Comparable<Country> { private int countryID; private String countryName; public Country(int countryID, String countryName) { this.countryID = countryID; this.countryName = countryName; } public int getCountryID() { return countryID; } public String getCountryName() { return countryName; } @Override public String toString() { return countryName; } @Override public int compareTo(Country another) { return this.getCountryID() - another.getCountryID();//ascending order // return another.getCountryID()-this.getCountryID();//descending order } } private class State implements Comparable<State> { private int stateID; private Country country; private String stateName; public State(int stateID, Country country, String stateName) { this.stateID = stateID; this.country = country; this.stateName = stateName; } public int getStateID() { return stateID; } public Country getCountry() { return country; } public String getStateName() { return stateName; } @Override public String toString() { return stateName; } @Override public int compareTo(State another) { return this.getStateID() - another.getStateID();//ascending order // return another.getStateID()-this.getStateID();//descending order } } private class City implements Comparable<City> { private int cityID; private Country country; private State state; private String cityName; public City(int cityID, Country country, State state, String cityName) { this.cityID = cityID; this.country = country; this.state = state; this.cityName = cityName; } public int getCityID() { return cityID; } public Country getCountry() { return country; } public State getState() { return state; } public String getCityName() { return cityName; } @Override public String toString() { return cityName; } @Override public int compareTo(City another) { return this.cityID - another.getCityID();//ascending order // return another.getCityID() - this.cityID;//descending order } } } 

This code uses the three data model classes Country , State and City , all of which implement Comparable<T> so that their instance can be sorted by their identifiers in List . You might want to use Comprator<T> here to sort alphabetically.

I used AdapterView.OnItemSelectedListener to track changes in the spinner widget that can be changed by the next spinner adapter.

I added some test data to demonstrate how the code works.

 Country Country1 Country2 ______|_____ _____|_________ | | | | State state1 state2 state3 state4 __|___ ___|___ __|___ __|____ | | | | | | | | City city1 city2 city3 city4 city5 city6 city7 city8 

enter image description here

+6
source

Try it the way it works

string.xml

 <resources> <string name="app_name">Spinner</string> <string name="hello_world">Hello world!</string> <string name="title_activity_main">MainActivity</string> <string-array name="country_array"> <item>India</item> <item>Pakisthan</item> <item>Sri Lanka</item> </string-array> <string-array name="city_india"> <item>Mumbai</item> <item>Chennai</item> <item>Kolkata</item> <item>Bangalore</item> </string-array> <string-array name="city_pakisthan"> <item>Karachi</item> <item>Lahore</item> <item>Faisalabad</item> <item>Rawalpindi</item> </string-array> <string-array name="city_srilanka"> <item>Colombo</item> <item>Dehiwala-Mount Lavinia</item> <item>Moratuwa</item> <item>Kotte</item> </string-array> </resources> 

activity_main.xml

 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="left" > <TextView android:id="@+id/textView" android:layout_width="130dp" android:layout_height="50dp" android:layout_alignParentTop="true" android:layout_centerHorizontal="true" android:layout_marginTop="15dp" android:gravity="center" android:text="Select County and City" android:textSize="15dp" /> <Spinner android:id="@+id/spinnerCountry" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@+id/textView" android:layout_centerHorizontal="true" android:layout_marginTop="28dp" android:entries="@array/country_array" /> <Spinner android:id="@+id/spinnerCity" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignLeft="@+id/spinnerCountry" android:layout_below="@+id/spinnerCountry" android:layout_marginTop="42dp" android:entries="@array/city_india" /> </RelativeLayout> 

MainActivity.java

 import android.app.Activity; import android.os.Bundle; import android.view.View; import android.widget.AdapterView; import android.widget.AdapterView.OnItemSelectedListener; import android.widget.ArrayAdapter; import android.widget.Spinner; public class MainActivity extends Activity implements OnItemSelectedListener { Spinner spinnerCountry, spinnerCity; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); spinnerCountry = (Spinner) findViewById(R.id.spinnerCountry); spinnerCity = (Spinner) findViewById(R.id.spinnerCity); spinnerCountry.setOnItemSelectedListener(this); } @Override public void onItemSelected(AdapterView<?> parent, View arg1, int pos, long arg3) { parent.getItemAtPosition(pos); if (pos == 0) { ArrayAdapter<CharSequence> adapter = ArrayAdapter .createFromResource(this, R.array.city_india, android.R.layout.simple_spinner_item); spinnerCity.setAdapter(adapter); } else if (pos == 1) { ArrayAdapter<CharSequence> adapter = ArrayAdapter .createFromResource(this, R.array.city_pakisthan, android.R.layout.simple_spinner_item); spinnerCity.setAdapter(adapter); } else if (pos == 2) { ArrayAdapter<CharSequence> adapter = ArrayAdapter .createFromResource(this, R.array.city_srilanka, android.R.layout.simple_spinner_item); spinnerCity.setAdapter(adapter); } } @Override public void onNothingSelected(AdapterView<?> arg0) { } } 
+2
source

I had what could be a similar problem, the reason is that onItemSelected is called when the spinner is created without being selected by the user. The cure was to add a listener via runnable to the spinner post event. Here is an example: -

  // Set Spinner onItemSelectedListener ie to act when a shop is selected. // Note!!! run on post, as a runnable, so that initial onItemSelected event // (at initialisation) is not captured current_shoplistspinner.post(new Runnable() { @Override public void run() { current_shoplistspinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener(){ @Override public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { currentshoplistcursor.moveToPosition(position); currentshopid = currentshoplistcursor.getLong(ShopperDBHelper.SHOPS_COLUMNN_ID_INDEX); Log.d(Constants.LOG,"ACTIVITY: " + THIS_ACTIVITY + " SECTION: Running - SHOPLIST OnItemSelectedLIstener" + "- SHOPID Extracted=" + currentshopid); currentaislelistcursor = shopperdb.getAislesPerShopAsCursor(currentshopid); current_aislelistspinneradapter.swapCursor(currentaislelistcursor); // if no aisles for this shop then don't show any products // TODO dialog to allow Aisle Add Log.d(Constants.LOG,"ACTIVITY: " + THIS_ACTIVITY + " SECTION: Running - SHOPLIST OnItemSelectedListener" + "- NEW AISLE COUNT=" + currentaislelistcursor.getCount()); if(currentaislelistcursor.getCount() < 1) { currentproductlistcursor = shopperdb.getNoProductsAsCursor(); current_productlistspinneradapter.swapCursor(currentproductlistcursor); // Also need to clear products per aisle as no ailse so no products // So use -1 as the aisleid when getting new cursor currentproductsperaisleecursor = shopperdb.getProductsperAisle(-1); current_productsperaislecursoradapter.swapCursor(currentproductsperaisleecursor); // Disable the ADD button as cannot add if no aisle or prodcuts findViewById(R.id.productusageedit_add).setVisibility(View.INVISIBLE); } else { currentproductlistcursor = shopperdb.getProductsAsCursor(); current_productlistspinneradapter.swapCursor(currentproductlistcursor); findViewById(R.id.productusageedit_add).setVisibility(View.VISIBLE); //Note!! as aislelist spinner has a new selecteditem it listener will //handle products per aisle refresh (unlike if no aisle) } } @Override public void onNothingSelected(AdapterView<?> parent) { } }); } }); 

Coincidentally, which came from the 3rd counter (shops, aisles and products). What would be like. Please note that this is just one of three. The logic that I used is to change the store (i.e. onItemSelected) and then change the aisle (no need to change the list of stores, since all stores are on the list), which will lead to a change in the product. If the passage has changed, then the products have changed.

0
source

Source: https://habr.com/ru/post/1247056/


All Articles