Android-ArrayAdapter дублирует элементы ListView
У меня есть виджет ListView
(расположенный ниже других элементов пользовательского интерфейса), который является частью Activity
, который не расширяет ListActivity
. Я пытаюсь написать базовую функцию, которая добавляет дополнительные элементы в ListView
при нажатии кнопки Button
. Эти данные получены из EditText
. Я определяю Adapter
, ArrayAdapter
в моем случае для ListView
в onCreate()
и устанавливаю адаптер для ListView
с помощью setListAdapter()
. Однако, когда я пытаюсь добавить дополнительный элемент к ListView
, два элемента добавляются вместо одного (элемент и его дубликат). Больше подробно об этом ниже.
Функция, которая отвечает на щелчок Button
и пытается добавить дополнительный элемент перед вызовом notifyDataSetChanged()
, выглядит следующим образом:
public void saveButton(View view){
EditText editText = (EditText) findViewById(R.id.edit_text);
String data = editText.getText().toString();
// duplication caused by this line
b.add(data);
ArrayAdapter adapter = (ArrayAdapter) listView.getAdapter();
adapter.add((String)data);
adapter.notifyDataSetChanged();
}
Когда я не включаю эту строку:
B. добавить (данные);
В список добавляется один элемент, который является ожидаемым поведением, поскольку adapter.add(Object)
добавляет дополнительный элемент в список. Однако еще более странно, что когда я не включаю adapter.add(Object)
элемент списка все еще отображается в списке.
public void saveButton(View view){
EditText editText = (EditText) findViewById(R.id.edit_text);
String data = editText.getText().toString();
b.add(data);
ArrayAdapter adapter = (ArrayAdapter) listView.getAdapter();
// not calling adapter.add() still includes an item in the list.
// adapter.add((String)data);
adapter.notifyDataSetChanged();
}
После небольшой отладки я обнаружил, что это происходит из-за добавления элемента данных в ArrayList
, т. е. b.add(data)
, где b-ArrayList строк, что приводит к включению элемента в ListView
, несмотря на то, что он не вызывает адаптер.добавить (объект)`.
Q1. Почему это происходит ?
Q2. Как расширение, означает ли это, что ArrayList
"связан" с моим ArrayAdapter
(поскольку он был построен с использованием ArrayList в качестве аргумента), подразумевая, что мне не нужно вызывать адаптер методы, такие как add () или clear (), чтобы манипулировать моим ListView
?
Вот полный код моей деятельности:
public class MainActivity extends Activity {
ListView listView;
ArrayList<String> b = new ArrayList<String>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
b.add("Liquorice");
b.add("Dairy Milk");
b.add("Rice Crispies");
b.add("Orange-Mint");
b.add("After-Tens");
listView = (ListView) findViewById(R.id.list_view);
ArrayAdapter adapter = new ArrayAdapter<String>(getApplicationContext(),R.layout.layout_file,b);
listView.setAdapter(adapter);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
public void saveButton(View view){
EditText editText = (EditText) findViewById(R.id.edit_text);
String data = editText.getText().toString();
b.add(data);
ArrayAdapter adapter = (ArrayAdapter) listView.getAdapter();
adapter.add((String)data);
adapter.notifyDataSetChanged();
}
}
Я также осмотрел другие посты SO, но они не дали мне ответов, которые я искал.
ArrayAdapter в android для создания простого listview
Почему нельзя добавлять/удалять элементы из ArrayAdapter?
Дублированные записи в ListView
Любое направление или объяснение по этому поводу буду очень признателен. Также большое спасибо за ваше время.
2 ответа:
Похоже, вы уже отыскали ответ. Предоставляя
ArrayList
ArrayAdapter
, вы, по сути, связали их. Чтобы обновить данные, все, что вам нужно сделать, это добавить новый элемент вArrayList
.Метод
.add()
- это просто короткий путь к этому. Все, что он делает, это добавляет предоставленный элемент вArrayList
. Вы можете добавить элемент в любом случае, просто не делайте этого в обоих направлениях.В чем же тогда смысл
notifyDataSetChanged()
? Просто потому, что вы обновилиArrayList
,это не значит, чтоListView
знает, что есть новые данные. Таким образом, новые данные могут существовать, но представление может не обновляться. ВызовnotifyDataSetChanged()
говоритListView
искать новые данные и перерисовывать себя так, чтобы пользователь видел изменение.
Из документации Android для
ArrayAdapter.notifyDataSetChanged()
:Notifies the attached observers that the underlying data has been changed and any View reflecting the data set should refresh itself.
Http://developer.android.com/reference/android/widget/ArrayAdapter.html#notifyDataSetChanged()
На адаптере проверьте, является ли представление нулевым, если это так, назначьте правильные представления из вашего макета, после if, установите значения.
@Override public View getView(int position, View convertView, ViewGroup parent) { ViewHolder viewHolder; if (convertView == null) { viewHolder = new ViewHolder(); LayoutInflater vi = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); convertView = vi.inflate(R.layout.customswipelayout, parent, false); viewHolder.name = (TextView) convertView.findViewById(R.id.rowTextView1); viewHolder.price = (TextView) convertView.findViewById(R.id.rowTextView2); viewHolder.stockCount = (TextView) convertView.findViewById(R.id.rowTextView3); convertView.setTag(viewHolder); mItemManger.bindView(view, position); } /* rest of your adapter code */ }
Это пример из одного моего, после того, как я закрываю оператор if, я присваиваю свои значения и возвращаю представление:
viewHolder = (ViewHolder) view.getTag(); final Object object = this.list.get(position); ImageView cmdDelete = (ImageView) view.findViewById(R.id.cmdDelete); cmdDelete.setOnClickListener //more personal code follows return view;
Теперь я прокручиваю свой список, и он отлично работает!