본문 바로가기

Eureka/Android

[Solution] getCheckedItemPositions() is wrong.

안드로이드에서 ListView 개발시 CHOICE_MODE_MULTIPLE 개발시 발생한 문제이다.
ListView에서 선택된 항목을 얻는 getCheckedItemPositions()에서 비정상적인 작동을 하는 것을 발견하였다.

문제 발생 코드를 보면 다음과 같다.

listView = (ListView) findViewById(R.id.fav_listview);
favAdapter = new FavoritesAdapter(this, R.layout.activity_favorites_entry, favList);
listView.setAdapter(favAdapter); listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE); listView.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { boolean checked = favAdapter.getItem(position).getChecked(); favAdapter.toggleSelection(position); listView.setItemChecked(position, false);                    // 분명히 false로 선택을 무조건 해제 한다. SparseBooleanArray selected = listView.getCheckedItemPositions();

for (int i = 0; i < selected.size(); i++) { favAdapter.getItem(selected.keyAt(i)).getTitle(); }

setTitle(selected.size() + "개 선택됨"); } });

setAdapter(favAdapter), setChoiceMode(ListView.CHOIDE_MODE_MULTIPLE) 모두 잘 마친 상태이고

분명 setItemChecked(position, false)로 호출했음에도 불구하고

setItemChcked(position, true)로 호출한 증상이 나타난다.


따라서 SparseBooleanArray selected = listView.getCheckedItemPositions()의 결과는

말할 것도 없이 선택하는 즉즉 size는 늘어나는 것을 확인 할 수 있는데...


해당 사항이 구글 docs에는 어디에도 명시되어 있지 않다.

그래서 CHOIDE_MODE_MULTIPLE_MODAL은 또 정상적이다.

구글이 왜 API 설계를 이렇게 했는지는 모르겠지만, 추측하건데 최적화 할 때 뭔가 문제가 일어난 것 같다.


그래서 해결방법은 다음과 같다.

for (int i = 0; i < selected.size(); i++) {
if (selected.valueAt(i)) {
int index = selected.keyAt(i);
mListView item = (mListView) listView.getAdapter().getItem(index); item.getTitle(); } } setTitle(checkedCount + "개 선택됨");

다른 부분은 다 동일시 두고 for문과 같이 valueAt()과 keyAt()으로 걸러줘야 한다.