Обновление ListView

Я работаю над программой, которая использует ListView который содержит строки, которые вводит пользователь. Я хочу, чтобы он перечислял каждую строку после того, как пользователь нажимает кнопку. Также я хочу, чтобы каждое строковое значение отображалось в ListView также быть в массиве, чтобы я мог управлять списком позже. Вот что у меня сейчас:

public ArrayList<String> choices = new ArrayList<String>();
public String[] choicesArray;

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    final ListView listView = (ListView) findViewById(R.id.listView1);
    choicesArray = new String[] { "You have not entered a choice yet" };
    final ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
            android.R.layout.simple_list_item_1, android.R.id.text1,
            choicesArray);
    listView.setAdapter(adapter);

    final Button addButton = (Button) findViewById(R.id.Button1);
    addButton.setOnClickListener(new View.OnClickListener() {

        public void onClick(View v) {
            EditText editText = (EditText) findViewById(R.id.edit_choice);
            String message = editText.getText().toString();
            adapter.add(message);

            //choices.add(message);
            //choicesArray = choices.toArray(choicesArray);

            //listView.setAdapter(adapter);
        }
    });
}

Этот код создает ошибку:

FATAL EXCEPTION: main
java.lang.UnsupportedOperationException
at java.util.AbstractList.add(AbstractList.java:404)
at java.util.AbstractList.add(AbstractList.java:425)
at android.widget.ArrayAdapter.add(ArrayAdapter.java:179)
at MainActivity$1.onClick(MainActivity.java:38)

2 ответа

Решение

Причина, по которой ваш список не обновляется, заключается в том, что вы никогда не добавляете свои элементы данных в адаптер. Вы только добавляете их в choicesArray это массив, который вы передали в новый конструктор ArrayAdapter().

Этот конструктор не привязывает адаптер к массиву, но в основном копирует массив в адаптер (во время вызова конструктора). Изменения, внесенные в массив после этого, не будут отражены в ArrayAdapter.

Мне нравится думать, что ArrayAdapter<> - это то же самое, что ArrayList<>, с дополнительным бонусом возможности генерировать дочерние представления для некоторого родителя AdpaterView. Вы можете передать это array[] для начала, и он инициализирует себя значениями в этом массиве, но он не связывает массив с адаптером или ListView. После этого первоначального вызова конструктора любые изменения одного из них не будут отражены в другом.

Поэтому вы должны изменить свой код, чтобы он выглядел так:

addButton.setOnClickListener(new View.OnClickListener() {

    public void onClick(View v) {
        EditText editText = (EditText) findViewById(R.id.edit_choice);
        String message = editText.getText().toString();
        adapter.add(message);

        //adapter.notifyDataSetChanged(); //<-- you might need to call this, but I think it might work without if you do it this way.
        //listView.setAdapter(adapter); //<-- you shouldn't need to call this each time. Once at the begining is enough.
    }
});

Редактировать:

измените ваш конструктор ArrayAdapter и удалите параметр choiceArray, чтобы вы остались с этим:

final ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
        android.R.layout.simple_list_item_1, android.R.id.text1);

после этого я думаю, что тебе следует идти. По сути, проблема заключалась в том, что, поскольку вы передавали массив, и поскольку массивы имеют фиксированный размер (у вас была длина = 1), он не позволял вам что-либо добавлять. Я подозреваю, что вы могли бы использовать ArrayList<String> вместо String[] если вы хотите, но, честно говоря, для вашей ситуации, я думаю, будет проще просто пропустить этот параметр все вместе и добавлять элементы непосредственно в ваш адаптер всякий раз, когда вам нужно будет добавить новые.

После добавления нового String в ваш список вы просто используете notifyDataSetChanged() вашего адаптера, который говорит адаптеру обновить дисплей, и он будет обновлять ListView с новой строкой

addButton.setOnClickListener(new View.OnClickListener() {

    public void onClick(View v) {

        EditText editText = (EditText) findViewById(R.id.edit_choice);
        String message = editText.getText().toString();
        choices.add(message);
        choicesArray = choices.toArray(choicesArray);

        adapter.notifyDataSetChanged();

    }
});

Обновить

Вы должны рассмотреть возможность внесения этого изменения тоже

choicesArray = new String[choices.size()];
choicesArray = choices.toArray(choicesArray);
Другие вопросы по тегам