Adapter의 notifyDataSetChanged() 메소드 관련 질문 드립니다.

조회수 21916회

안녕하세요. 제가 지금 메모장 어플리케이션을 만들어보면서 안드로이드 공부를 해보고 있습니다.

메모장 안에는 ListView가 들어가고 Adater에는 BaseAdapter를 상속받아서 정의한 CustomAdapter가 있습니다. 리스트뷰에 들어가는 아이템에는 텍스트뷰 하나만 나오고 있고요.

[메모 추가] 버튼을 누르면 새로운 액티비티가 띄워지고 거기에 메모를 입력하고 완료를 누르면 onActivityResult에서 입력받은 메모를 ArrayList에 집어넣고 adapter.notifyDataSetChanged()를 호출합니다.

ArrayList<MemoItem> mArrayList = new ArrayList<MemoItem>();
Context mContext;

public MemoAdapter(ArrayList<MemoItem> arrayList, Context context) {
        this.mArrayList = arrayList;
        this.mContext = context;
}

CustomAdapter 클래스 내부에 필드로 ArrayList를 두고

mMemoAdapter = new MemoAdapter(mArrayList, getApplicationContext());

액티비티 안에서 어뎁터를 생성할 때 어뎁터 안에서도 가지고 있는 mArrayList를 넘겨주게 되어있습니다.

그래서 액티비티의 onActivityResult가 호출되고 그 안에서 액티비티 안에 있는 mArrayList.add()를 하여 아이템 하나를 추가하면 Adapter 안에 있는 ArrayList와 같은 것을 가리키므로 notifyDataSetChanged()를 호출하면 리스트뷰가 업데이트가 될 줄 알았습니다.

리스트뷰 안에 새로운 아이템이 생기긴 하였는데, 문제는 그 안에 있는 내용물이 보이지 않는 다거나, 이미 존재하는 아이템의 것과 같은것을 출력하는 등의 문제가 생겼었습니다.

관련 정보를 adpater notifyDataSetChanged 라고 구글링을 해보니 뭔가 많이 있긴한데 이해가 잘 되지않아서 이렇게 질문드립니다.

스택오버플로우에 있는 어떤 답변은 액티비티 안에서 adapter를 새로 만들고 다시 listview.setAdapter를 하라고 하던데 그렇게 할경우 성능에 좋지 않을 것 같다는 생각이 들어서 그 방법은 쓰지않았습니다.

혹시 이 문제를 해결할 방법이 있을까요? 아니면 왜 이런건지... notifyDataSetChanged 메소드에 문제가 있는 것인지...

  • (•́ ✖ •̀)
    알 수 없는 사용자
  • 제대로 코드를 짰다면 list에 add를 하고 notifyDataSetChanged()를 호출하면 리스트뷰가 정상적으로 갱신되는것이 맞습니다. 리스트뷰의 내용물도 제대로 보여야하구요.. 혹시 코드를 좀더 보여주실 수 있나요? 알 수 없는 사용자 2016.4.14 23:51

1 답변

  • notifyDataSetChanged를 호출할 때, Ui 스레드에서 호출하고 있나요?

     // UI를 담당하는 Thread를 이용하여 notifyDataSetChanged()를 호출하는 방법
      getContext().runOnUiThread(new Runnable() {
          public void run() {
              adapter.notifyDataSetChanged();
          }   
     });
    

    그리고 새 adapter를 만들어서 setAdapter를 다시 호출할 경우... 스크롤 위치가 초기화됩니다. 성능상의 문제를 떠나서, 결과물을 사용자가 사용하기 쉽지 않을 것 같네요.

    [ 추가 답변 ]

    그렇다면 Custom Adapter 생성할 때 사용한 List 전체를 갱신하는 방향으로 시도해보세요.

    temporalList.addAll(adapterList); // 임시 리스트에 Adapter에 연결한 list의 내용을 모두 담고
    temporalList.add(newItem); // 새로운 아이템을 등록한 후에
    adapterList.clear(); // adapter에 연결한 list의 내용을 모두 지웠다가
    adapterList.addAll(temporalList); // 임시리스트의 내용을 모두 adapter에 연결한 리스트에 추가하기
    adapter.notifyDataSetChanged(); // 그리고 notifyDataSetChanged를 호출해보세요.
    

    해놓고 보니 깔끔하지는 않네요. 다른 방법은 CursorAdapter( 링크1, 링크2, 링크3 )를 쓰는것을 추천하네요.

    기타 참고 : 링크4

    • 답변 감사합니다 알려주신 방법으로 하였는데 갱신이 바로는 안되고 스크롤을 하여 아이템이 화면 밖으로 나갔다가 다시 보이면 그때서야 갱신이 되네요 ㅠ 알 수 없는 사용자 2016.4.14 11:55
    • Acitivity 안에 있어서 this.runOnUiThread로 하였습니다 알 수 없는 사용자 2016.4.14 11:56
    • 추가로 답변한 것처럼 해보세요. 허대영(소프트웨어융합대학) 2016.4.14 15:20

답변을 하려면 로그인이 필요합니다.

프로그래머스 커뮤니티는 개발자들을 위한 Q&A 서비스입니다. 로그인해야 답변을 작성하실 수 있습니다.

(ಠ_ಠ)
(ಠ‿ಠ)