Передавайте строковые переменные по ссылке на setOnItemSelectedListener нескольких счетчиков.

Хорошо, я почитал и вижу, что Java проходит только по значению, а не по ссылка, поэтому я не знаю, как это сделать.

  • У меня есть 6 Spinners в Android Activity, которые заполнены разными запросами SQLite.
  • Код для заполнения каждого Spinner и установки OnItemSelectedListener очень похож, поэтому я надеялся провести рефакторинг в один метод и вызвать его 6 раз с каждым идентификатором Spinner и запросом Sqlite.
  • Как заставить Spinner onItemSelectedListener изменить правильный элемент экземпляра на каждом другом Spinner?

    public void fillSpinner(String spinner_name, final String field_name) {
    // This finds the Spinner ID passed into the method with spinner_name
    // from the Resources file. e.g. spinner1
    int resID = getResources().getIdentifier(spinner_name, "id",
            getPackageName());
    Spinner s = (Spinner) findViewById(resID);
    final Cursor cMonth;
    // This gets the data to populate the spinner, e.g. if field_name was
    // strength = SELECT _id, strength FROM cigars GROUP BY strength
    cMonth = dbHelper.fetchSpinnerFilters(field_name);
    startManagingCursor(cMonth);
    String[] from = new String[] { field_name };
    int[] to = new int[] { android.R.id.text1 };
    SimpleCursorAdapter months = new SimpleCursorAdapter(this,
            android.R.layout.simple_spinner_item, cMonth, from, to);
    months.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
    s.setAdapter(months);
    // This is setting the Spinner Item Selected Listener Callback, where
    // all the problems happen
    s.setOnItemSelectedListener(new OnItemSelectedListener() {
        public void onItemSelected(AdapterView<?> parent, View view,
                int position, long id) {
            Cursor theCursor = (Cursor) parent.getSelectedItem();
            // This is the problem area.
            object_reference_to_clas_member_of_field_name = theCursor
                    .getString(theCursor.getColumnIndex(field_name));
        }
    
        public void onNothingSelected(AdapterView<?> parent) {
            // showToast("Spinner1: unselected");
        }
    });
    

    }

Вы вызываете этот метод следующим образом: fillSpinner("spinner1","strength");.

Он находит счетчик с идентификатором spinner1 и запрашивает базу данных для поля strength. field_name, которое является сильным в этом примере, должно было быть объявлено окончательной переменной для использования в onItemSelectedListener, иначе я получил бы ошибку Cannot refer to a non-final variable field_name inside an inner class defined in a different method.

Но как заставить onItemSelectedListener изменять значение другого члена экземпляра, когда используется каждый отдельный Spinner? Это самая важная строка кода: object_reference_to_clas_member_of_field_name = theCursor .getString(theCursor.getColumnIndex(field_name));

Я не могу использовать окончательную строку, поскольку переменная, очевидно, изменится, когда пользователь выберет другое значение. Я много читал и не нашел решения. Я могу просто скопировать и вставить этот код 6 раз и забыть о рефакторинге, но мне бы очень хотелось узнать элегантное решение. Напишите комментарий, если вы не понимаете мой вопрос, я не уверен, что хорошо объяснил себя.


person georgiecasey    schedule 18.01.2012    source источник
comment
на самом деле непонятно, что вы хотите и с какой проблемой вы сталкиваетесь в onItemSelected. Пожалуйста, уточните подробнее.   -  person jeet    schedule 18.01.2012
comment
Cannot refer to a non-final variable field_name inside an inner class defined in a different method., почему бы вам не объявить field_name глобально в основном классе.   -  person Lalit Poptani    schedule 21.01.2012


Ответы (3)


Вы можете сделать это, передав дополнительный класс в качестве параметра метода fillSpinner:

А. Создайте interface

public interface OnSpinnerValueSelected {
    void onValueSelected(String selectedValue);
}

B. Немного измените свой метод:

public void fillSpinner(String spinner_name, final String field_name,
                    final OnSpinnerValueSelected valueChangeListener) {

    // Prepare spinner

    s.setOnItemSelectedListener(new OnItemSelectedListener() {

        public void onItemSelected(AdapterView<?> parent, View view,
                     int position, long id) {
            Cursor theCursor = (Cursor) parent.getSelectedItem();

            valueChangeListener.onValueSelected(theCursor
                           .getString(theCursor.getColumnIndex(field_name)));
        }

        public void onNothingSelected(AdapterView<?> parent) {

        }
    });
}

C. предоставить слушателю:

fillSpinner("spinner1","strength", new OnSpinnerValueSelected() {
    public void onValueSelected(String selectedValue) {
        yourObject.setField(selectedValue);
    }
});
person Jin35    schedule 21.01.2012
comment
Отлично, это сработало и кажется лучше, чем жестко запрограммированные имена переменных в самой рефакторинговой функции. Таким образом, в Java вы не можете передать объект String по ссылке, но вы можете передать конечный объект, у которого есть метод для установки значения объекта String. - person georgiecasey; 21.01.2012

Рефакторинг вашего слушателя в новый «класс». Инициализируйте с правильными аргументами/экземплярами по мере необходимости, чтобы повторяющийся «код» можно было использовать повторно.

person panzerschreck    schedule 18.01.2012
comment
Да да, это звучит почти правильно. Я попробую это и отчитаюсь, ура - person georgiecasey; 18.01.2012

Верно, вот как мне это удалось, но я все еще открыт для новых предложений для принятого ответа, и я также создал награду.

Я не создавал новый класс вроде panzerschreck предложил, поэтому я публикую это как новый ответ на мой собственный вопрос. Немного взлома, но я только что создал оператор if..then..else в слушателе, чтобы проверить, какой счетчик был выбран, а затем установить другой член экземпляра.

s.setOnItemSelectedListener(new OnItemSelectedListener() {
        public void onItemSelected(AdapterView<?> parent, View view,
                int position, long id) {
            Cursor theCursor = (Cursor) parent.getSelectedItem();
            if (field_name.equalsIgnoreCase("strength")) {
                strength=theCursor.getString(theCursor.getColumnIndex(field_name));
            } else if (field_name.equalsIgnoreCase("ring")) {
                ring_gauge=theCursor.getString(theCursor.getColumnIndex(field_name));
            } else if (field_name.equalsIgnoreCase("country")) {
                country=theCursor.getString(theCursor.getColumnIndex(field_name));
            } else if (field_name.equalsIgnoreCase("wrapper")) {
                wrapper=theCursor.getString(theCursor.getColumnIndex(field_name));
            } else if (field_name.equalsIgnoreCase("length")) {
                length=theCursor.getString(theCursor.getColumnIndex(field_name));
            } else if (field_name.equalsIgnoreCase("price")) {
                price=theCursor.getString(theCursor.getColumnIndex(field_name));
            } 
            // showToast(category);
        }

        public void onNothingSelected(AdapterView<?> parent) {
            // showToast("Spinner2: unselected");
        }
    });

Вот члены класса

private String strength,ring_gauge,country,wrapper,length,price;

Немного хака, но без Java, позволяющей действительно передавать объекты по ссылке, это все, что я мог сделать.

person georgiecasey    schedule 18.01.2012
comment
Я должен сказать, что не рекомендуется ставить операторы «если». По возможности также избегайте жестко закодированных значений, это кошмар обслуживания! - person panzerschreck; 19.01.2012
comment
Я не мог использовать оператор switch для строк, если вы это имели в виду. Я знаю, я тоже не хотел использовать жестко закодированные значения, но есть ли другой выбор. Я хотел бы знать элегантное решение этого. Я попытался создать новый класс в качестве слушателя, как вы предложили, но снова проблема заключается в том, как я передаю члены экземпляра по ссылке, а не по значению конструктору этого нового класса слушателя. - person georgiecasey; 19.01.2012