마스터Q&A 안드로이드는 안드로이드 개발자들의 질문과 답변을 위한 지식 커뮤니티 사이트입니다. 안드로이드펍에서 운영하고 있습니다. [사용법, 운영진]

Viewpager사용시에 ListView에서 IlligalstateException발생...

0 추천

자꾸 백그라운드에서 norifyDataSetChanged() 호출하지 말라네요...

전 핸들러로 감싸놨는데 짜증나서 3중으로 감싸봤습니다...

new Handler(Looper.getMainLooper()).post(new Runnable(){

 

new Handler(Looper.getMainLooper()).post(new Runnable(){

 

new Handler(Looper.getMainLooper()).post(new Runnable(){

notifyDataSetChanged();

})


})


});

...

근데도 안됩니다...

도와주세요 ㅜ

 

수상한i (8,050 포인트) 님이 2013년 3월 2일 질문

3개의 답변

+2 추천
음 저도 저런 경우가 있었는데....

재가 겪었던 방식은 스레드하나를 생성하고 디비작업하고 리스트를 갱신하는 작업이였는데

그것을 여러번하게 되니까 스레드가 여러개 생성되어서...백그라운드에서 했다고 하면서

죽는경우가 발생하더군요... 그래서 스레드를 체크해서(살아있는지 않살아있는지)

않살아있는경우에만 실행하게만들었더랬죠.. 그런것과 유사한 상황이지않은가 싶습니다
건방진프로그래머 (26,630 포인트) 님이 2013년 3월 2일 답변
근데 저거는... 처음에 어플을 실행했을때 그럽니다...
ViewPager쓰고있는데 탭은 제가 만든거 쓰고요 어떤 방법으로 진입하든 listview를 보면 저런에러를 뿜어냅니다(그것도 가끔씩만요)
db쿼리문은 처음에 3개돌아가고요 데이터 추가될때 1번씩 돌아갑니다...
그리고 모두 AsyncTask쓰고요... onpostexecute 이후엔 사라지지 않나요???
AsyncTask 를 사용하신다면, notifyDataSetChanged(); 를 저런식이 아니라, onPostExecute 로 notifyDataSetChanged을 옮겨서 실행시켜 보시겠어요?

생각해보니, 그래도 문제가 되겠군요. 이게 약간 웃기는 api 구성과 결부 되어 있는데, 일단, UI 갱신시에는 UI와 관련된 자료형의 읽기/쓰기를 UI 쓰레드내에서만 하도록 해두어야 합니다.

AsyncTask 의 경우에 버전별로 동작 방식이 약간 다릅니다. 아마도, '수상한i' 님께서는 AsyncTask 를 Thread queue 로 생각하고 작업하신거 같은데, 진저에서는 pool 로 최대 5개가 동시에 동작하고 허니컴 이후에는 기본 옵션이 queue 처럼 동작합니다. 아마 이런 상황의 부수 효과 같이 보이기도 하는데, 작업하시는 폰의 버전이 어떻게 되나요?
아뇨 저건 제가빡쳐서 adapter내에 미친짓해논거에요...
그리고 전 모든 list추가 작업을 h.post(UI내에서) 에서 처리합니다
근데 안되요...
listview는... 문제가 없구요...짜증나는건 db를 제외하고 모두다 핸들러 내부에서 하는데
( 데이터추가는 db에서 로드한뒤 final 변수를 하나 생성해서 핸들러에서 처리합니다) 저 에러가 발생합니다... 좀 있다가 소스 올리고 재질문할게요...
+1 추천

 

inerClass로 어댑터를 구현하셨어도 내부에서 사용 할 수 있는 변수
전역처럼 사용 할 수 있는것들에 한정됩니다.
클래스 선언부에서 static 변수를 바인드해서 사용하시면 됩니다.
 
그리고 notifyDataSetChanged()는 데이터의 변경이 끝났을때
UI스레드에게 알려주어 변경된 컴포넌트들을 invalid 하기위한게 최종 목적이므로

백그라운드에서 굳이 호출 하실 필요가 없습니다.
UI의 onResume 이나 onCreate에서 호출 한번씩 해주셔도 됩니다.

 

Noizbuster (11,970 포인트) 님이 2013년 3월 2일 답변
가끔은 백그라운드에서 해줄필요성이 있을때가 있습니다
그건 케이스바이케이스죠...
0 추천
이게 무슨 소스죠?

혹시 이벤트 발생 -> 핸들러 생성 -> 쓰레드 생성 -> notifydatasetchanged() 라는 생각으로 작성하신 코드라면

조금 틀렸습니다 .

 

핸들러를 만들어놓고 이벤트가 발생했을때 핸들러에게 메시지를 보내서

핸들러가 쓰레드를 생성해서 notify 하도록 바꿔주셔야 될 것 같스빈다.
마플 (3,720 포인트) 님이 2013년 3월 2일 답변
아뇨 그런게 아니고 저건 그냥 리시트아답터내부에서 만든 refresh()의 코드입니다
실수했네요 ㄷ;
그리고 핸들러는 2가지 방법으로 가능합니다...
저렇게 실시간으로 만들어도 되요 그리고 원래는 h라는 변수로 했는데 깨지길래 저렇게 한거구요..
...