ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

java – 国家,州和城市微调器无法正常工作

2019-06-11 16:48:52  阅读:169  来源: 互联网

标签:java android android-studio android-spinner android-volley


我一直在研究注册表单应用程序,其中使用了很少的微调器小部件.微调器用于选择国家,州和城市.因此,这些微调器需要以某种方式相互连接(下面的代码将显示我是如何尝试实现的).

表格代码:

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>

上面的代码有更多的小部件,你可以在java文件中找到它们;我没有将它们包含在上面的代码中,因为它会使它太长.

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 one rrorResponse(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));
    }


}
}

有一个PHP API,它根据url返回Country,State或City的json.例如:
    http://www.example.com/location_api/api.php?type=getCountries
http://www.example.com/location_api/api.php?type=getStates\u0026amp;countryId=12
http://www.example.com/location_api/api.php?type=getCities\u0026amp;stateId=1

在onItemSelected中,我试图相对于前一个微调器动态设置微调器.例如,每当选择country spinner项时,我都会设置状态微调器.我正在通过if-else块检查这个;如果条件检查是否选择了奥地利(列表中的一个国家;随机选择),则设置状态微调器,否则也设置状态微调器.这样我最终根据country spinner元素设置状态微调器.

要向API指定正在选择的国家/地区,我正在使用itemId,其中包含国家/地区微调器中所选项目的ID.
long itemId = country_spinner.getSelectedItemId();

然后当我有Id我调用getData方法设置结果ArraryList并将其分配给微调器状态.

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

上面的代码使应用程序在运行时崩溃并出现以下错误(我认为其中只有一部分可能有用,完整的Logcat文件在这里:Link):

——— 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)

Throwing OutOfMemoryError “Failed to allocate a 1667853436 byte
allocation with 777786 free bytes and 381MB until OOM”

解决方法:

在您的代码中,您将不得不更改微调器的适配器,该适配器依赖于其他微调器.

City微调器适配器根据State微调器适配器更改
那也是
Statespinner适配器更改取决于Countryspinner适配器,

我已经编写了一个示例代码来演示如何实现这一点,我编写了一个通用代码,其他人可以在阅读答案时理解,随意建议并根据您的要求进行更改.

代码也可以在Github上获得,另一个例子可以帮助您从它使用的网络下载JSON数据,OkHttp,GSON和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
        }
    }
}

该代码使用三个数据模型类Country,State和City,它们都实现了Comparable< T>因此,他们的实例可以根据列表中的ID进行排序,您可能希望使用Comprator< T>这里按字母顺序排序.

我使用了AdapterView.OnItemSelectedListener来跟踪Spinner小部件中可以更改后续微调器适配器的更改.

我添加了一些测试数据来演示代码的工作原理

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

enter image description here

标签:java,android,android-studio,android-spinner,android-volley
来源: https://codeday.me/bug/20190611/1219948.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有