Android - переменная класса, которой не назначено значение setOnItemSelectedListener во времени - PullRequest
0 голосов
/ 03 июня 2018

Я пишу приложение для конвертации валют и использую запросы Volley для отправки запроса в API для получения коэффициентов конвертации.

У меня есть два счетчика (от валюты и целевой валюты) прямо сейчас.У меня есть три функции: одна для добавления элементов в счетчик, одна для добавления слушателей при нажатии кнопки и одна для отправки запроса залпа для получения информации JSON.

Я полагаю, что я вызываю функции в правильном порядке, однако, по какой-то причине кажется, что значение toSpinnerText и fromSpinnerText не установлено на значение счетчиков.На мой взгляд, они должны быть установлены до отправки запроса на URL, так как я звоню addItemsOnToSpinner() до jsonSendRequest().Но когда я выполнял отладку с помощью вызовов журнала, значения toSpinnerText и fromSpinnerText все еще являются пустыми строками, когда строится строка URL.

Вот что у меня так далеко.Спасибо.

public class MainActivity extends AppCompatActivity {

RequestQueue rq;
Double conversionDouble;

Spinner toSpinner, fromSpinner;
String toSpinnerText = "";
String fromSpinnerText = "";
private Button convertBtn;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    addItemsOnToSpinner();
    addListenerOnButton();
    jsonSendRequest();

    Button convertBtn = (Button) findViewById(R.id.convertBtn);
    final EditText fromAmountEditText = findViewById(R.id.fromAmountEditText);

    convertBtn.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            TextView toAmountTextView = findViewById(R.id.toAmountTextView);
            DecimalFormat percentageFormat = new DecimalFormat("0.00");
            Double fromAmount = Double.parseDouble(fromAmountEditText.getText().toString());
            String result = "$" + percentageFormat.format(conversionDouble*fromAmount);
            toAmountTextView.setText(result);
        }
    });
    rq = Volley.newRequestQueue(this);

}

public void jsonSendRequest() {

    RequestQueue queue = Volley.newRequestQueue(this);
    // String url = "http://free.currencyconverterapi.com/api/v3/convert?q=CAD_USD&compact=ultra";
    String url = "http://free.currencyconverterapi.com/api/v3/convert?q=" + fromSpinnerText + "_" + toSpinnerText  + "&compact=ultra";

    // Request a string response
    StringRequest stringRequest = new StringRequest(Request.Method.GET, url,
            new Response.Listener<String>() {
                @Override
                public void onResponse(String response) {
                    JSONObject jsonobject = null;
                    try {
                        jsonobject = new JSONObject(response);
                    } catch (JSONException e) {
                        e.printStackTrace();
                    }
                    if (jsonobject.has(fromSpinnerText + "_" + toSpinnerText)) {
                        try {
                            conversionDouble = jsonobject.getDouble(fromSpinnerText + "_" + toSpinnerText);
                            // conversionDouble = jsonobject.getDouble(fromSpinnerText + "_" + toSpinnerText);
                        } catch (JSONException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }, new Response.ErrorListener() {
        @Override
        public void onErrorResponse(VolleyError error) {

        }
    });

// Add the request to the RequestQueue.
    queue.add(stringRequest);
}

public void addItemsOnToSpinner(){

    Spinner toSpinner = (Spinner) findViewById(R.id.toSpinner);
    Spinner fromSpinner = (Spinner) findViewById(R.id.fromSpinner);

    List<String> currency = new ArrayList<String>();
    currency.add("USD");
    currency.add("CAD");
    currency.add("CNY");

    ArrayAdapter<String> dataAdapter = new ArrayAdapter<String>(
     this, android.R.layout.simple_spinner_item, currency
    );

    dataAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);


    toSpinner.setAdapter(dataAdapter);
    fromSpinner.setAdapter(dataAdapter);

    fromSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
        @Override
        public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
            String fromSpinnerText = (String) parent.getItemAtPosition(position);
        }

        @Override
        public void onNothingSelected(AdapterView<?> parent) {

        }
    });

    toSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
        @Override
        public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
            String toSpinnerText = (String) parent.getItemAtPosition(position);
        }

        @Override
        public void onNothingSelected(AdapterView<?> parent) {

        }
    });

}

public void addListenerOnButton() {

    Spinner fromSpinner = (Spinner) findViewById(R.id.fromSpinner);
    Spinner toSpinner = (Spinner) findViewById(R.id.toSpinner);
    Button convertBtn = (Button) findViewById(R.id.convertBtn);

}

}

Ответы [ 2 ]

0 голосов
/ 03 июня 2018

Прежде всего, как вы упомянули в комментарии, который вам не нужен addListenerOnButton()

Я постарался прокомментировать в коде как можно больше, чтобы вы могли следить за изменениями, которые я сделал.

public class MainActivity extends AppCompatActivity {
    //Always create a TAG it is very useful when logging to the logcat!
    private static final String TAG = MainActivity.class.getSimpleName();

    //Not used! Not needed!
    //RequestQueue rq = null;

    // I like to have all my class variables defined at the beginning--even if it is just null!
    //Class variable to hold the object throughout the class!
    Spinner toSpinner = null;
    Spinner fromSpinner = null;
    Button convertBtn = null;

    //Class variable to hold the object throughout the class!
    EditText fromAmountEditText = null;
    TextView toAmountTextView = null;

    String toSpinnerText = "";
    String fromSpinnerText = "";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        createSpinnerAddData();

        // convertBtn is a class variable defined above--do not create a local variable here
        convertBtn = (Button) findViewById(R.id.convertBtn);

        // fromAmountEditText is a class variable defined above--do not create a local variable here
        fromAmountEditText = findViewById(R.id.fromAmountEditText);
        // toAmountTextView is a class variable defined above--do not create a local variable here
        toAmountTextView = findViewById(R.id.toAmountTextView);

        convertBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //Perform your request here--after the currencies have been selected!
                jsonSendRequest();
            }
        });
        //Dont use it--Dont need it!
        //rq = Volley.newRequestQueue(this);
    }

    // this does not need to be public!
    private void jsonSendRequest() {

        RequestQueue queue = Volley.newRequestQueue(this);
        // String url = "http://free.currencyconverterapi.com/api/v3/convert?q=CAD_USD&compact=ultra";
        String url = "http://free.currencyconverterapi.com/api/v3/convert?q=" + fromSpinnerText + "_" + toSpinnerText  + "&compact=ultra";

        // Request a string response
        StringRequest stringRequest = new StringRequest(Request.Method.GET, url,
                new Response.Listener<String>() {
                    @Override
                    public void onResponse(String response) {
                        //onResponse is asynchronous it is called when the data is available, but it executes on the UI thread 
                        JSONObject jsonobject = null;
                        try {
                            jsonobject = new JSONObject(response);
                        } catch (JSONException e) {
                            e.printStackTrace();
                        }
                        if (jsonobject.has(fromSpinnerText + "_" + toSpinnerText)) {
                            try {
                                //conversionDouble is only used here so it can be a local variable!
                                Double conversionDouble = jsonobject.getDouble(fromSpinnerText + "_" + toSpinnerText);
                                // conversionDouble = jsonobject.getDouble(fromSpinnerText + "_" + toSpinnerText);

                                //now the data has returned from the async request and is ready to be used..
                                //...do the conversion, now!
                                DecimalFormat percentageFormat = new DecimalFormat("0.00");
                                Double fromAmount = Double.parseDouble(fromAmountEditText.getText().toString());
                                String result = "$" + percentageFormat.format(conversionDouble*fromAmount);
                                toAmountTextView.setText(result);

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

            }
        });

        // Add the request to the RequestQueue.
        queue.add(stringRequest);
    }

    // this does not need to be public!
    private void createSpinnerAddData(){

        //The spinners were already defined in the onCreate method--please do not create local variables!!
        //Spinner toSpinner = (Spinner) findViewById(R.id.toSpinner);
        //Spinner fromSpinner = (Spinner) findViewById(R.id.fromSpinner);

        // fromSpinner is a class variable defined above--do not create a local variable here
        fromSpinner = (Spinner) findViewById(R.id.fromSpinner);
        // toSpinner is a class variable defined above--do not create a local variable here
        toSpinner = (Spinner) findViewById(R.id.toSpinner);

        List<String> currency = new ArrayList<String>();
        currency.add("USD");
        currency.add("CAD");
        currency.add("CNY");

        ArrayAdapter<String> dataAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, currency);

        dataAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); 

        toSpinner.setAdapter(dataAdapter);
        fromSpinner.setAdapter(dataAdapter);

        fromSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
                //This has also been defined as a class variable--please do not create local variable!!
                //String fromSpinnerText = (String) parent.getItemAtPosition(position);
                //...Instead use the class variable
                fromSpinnerText = (String) parent.getItemAtPosition(position);
                Log.e(TAG, "fromSpinnerText = " + fromSpinnerText);
            }

            @Override
            public void onNothingSelected(AdapterView<?> parent) {

            }
        });

        toSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
                //Same principle as above
                toSpinnerText = (String) parent.getItemAtPosition(position);
                Log.e(TAG, "toSpinnerText = " + toSpinnerText);
            }

            @Override
            public void onNothingSelected(AdapterView<?> parent) {

            }
        });
    }

}

Также упомянуто выше в комментарии: очень важно, чтобы вы узнали разницу между public, protected и private методами и переменными, а также область видимости переменных ... когдаиспользуйте переменные класса и локальные переменные.Это поможет вам в будущем программисту!Удачи и продолжайте учиться!

Если у вас есть какие-либо вопросы - я сделаю все возможное, чтобы помочь.

0 голосов
/ 03 июня 2018

Как вы выберете элемент в fromSpinnerText, если создадите для него новую локальную переменную.Вы сохраняете выбранное значение в локальной переменной, а не в глобальной переменной, созданной в верхней части действия.

Замените

String fromSpinnerText = (String) parent.getItemAtPosition(position);

на

fromSpinnerText = (String) parent.getItemAtPosition(position);

и замените

String toSpinnerText = (String) parent.getItemAtPosition(position);

до

toSpinnerText = (String) parent.getItemAtPosition(position);
...