안드로이드 개발 질문/답변
(글 수 45,052)
안녕하세요.
하기 질문에 앞서, 나름 ListView를 사용해 보았고, ListView에 대한 많은 글들과 Q&A를 읽고
질문을 드립니다.
사전 설명..
ListView를 사용자 레이아웃을 적용하여 사용중에 있습니다.( 한 Item에 ImageView, TextView, Button 등이 들어갑니다.)
Item마다 각 객체 정보들은 따로 클래스를 만들어 저장해두고 사용하고 있습니다.
그래서 getView()에서 view가 null 일때만 새로이 정보를 만들어 내고, 나머진 저장해둔 정보를 사용합니다.
또한, TextView나 Button 등은 1초에도 수번씩 정보가 변경 될 수도 있습니다.
버튼 같은 경우는 클릭했을 때, 상태 클래스를 살펴보고, 그에 따라 버튼 Text라든지 이미지도 변경됩니다.
현 문제점..
getView()에서가 아닌 TextView나 Button 객체에 직접적으로 setText 형태로 데이터를 넣으니
ListView에 바로 데이터가 갱신이 되어 보입니다.
헌데, 이상하게 제가 setText를 1번 행에 했다고 한다면.. 저~ 5번 행에서도 동일한 text가 적용되 보이게 됩니다.
하지만 실제 데이터를 읽어보면 원래 데이터가 제대로 저장 돼 있습니다. 보이기만 그렇게 보이더라구요..;;
심지어는 invisible 상태의 TextView가 값자기 보이는 경우도 있습니다.
위 상태로 인해 notifyDataSetChanged() 함수를 setText하고 난 다음 호출 해주니
위 상황은 싸그리~ 없어졌습니다.
헌데!!! Item에 Button이 있다고 하지 않았습니까..?? 그 버튼들을 하나씩 클릭하다 보면
다른 Listener가 호출 돼 버립니다. 예로, 1번 행에서 버튼을 클릭하면 4번행의 버튼 리스너가 동작(onClick)한다는 거죠.
그래서요. 제가 마지막으로 setText를 직접 하지 않고.. String은 수정된 상태에서
invalidate() 함수를 통해 갱신만 하게 했거든요. notifyDataSetChanged() 이 함수는 쓰지 않구요..
그랬더니 위 첫번째랑 두번째 문제점이 생기지 않는 것입니다.
헌데!!! 화면이 바로 갱신이 안 되고 스크롤을 움직여야지 갱신되는 문제가 있더라구요.
이 총체적 난국을 어떻게 해결 할 수 있을까요..ㅠㅠ?
PS. ListView에서 하는 역할은 안드로이드 마켓처럼 리스트에서 특정 아이템의 버튼을 클릭해서
다운받는 기능을 하는데요. 다운받은 %를 해당 Item의 TextView를 통해서 계속 보여주고 있는 상태입니다.
긴글 읽어주셔서 감사합니다.
2010.05.12 16:28:54
소스 코드를 발췌 해서 놓고 설명하심이 좋았을껀대 아쉽내요
정리하자면
1. getView() 에서 view가 null 일때 새로이 정보를 만들어서 설정한다.
- null이 아니면 어떤 저장된 데이터를 설정한다.
2. 어떤 이벤트가 들어오면 List item의 내용이 바뀐다
문제점
1. getView()가 아닌곳에서 List item의 값을 변경하는대 변경한 item의 위치가 아닌 다른곳의 값이 같이 변경된다.
-> getView에서 view를 재사용하시는대 데이터 설정을 잘못하고 있는거 같내요
public View getView(int position, View convertView, ViewGroup parent) {
if( convertView == null )
{
LayoutInflater inflater = getLayoutInflater()
View view = inflater.inflate( R.layout.....);
convertView = view;
}
}
제일 처음에 올려놓았던 글 봤을때 대충 이런식으로 하셨을건대 if문 제거 해보세요
3. 다른방식으로 했더니 잘되는대 setText를 직접 하지 않고.. String을 변경하셔서 하셧다...
-> 솔직히 뭔소린지 모르겠어요 이건...
참조하는 data인 String 변수값을 바꾼다고 item의 값이 바로 바뀌진 않습니다. 스크롤 해서 변경되었다는건
화면 갱신을 하려고 getView()가 호출 되었기 때문에 getView() 내부에서 data인 String 변수를 보고 setText()를
통해서 item의 값을 변경 했기 때문에 변경된 것입니다.
-> ListView를 가져와서 직접 item에 접근하셔서 setText()를 통해서 값 바꾼후에 invalidate() 하시면 됩니다.
2010.05.13 08:47:57
안녕하세요. 위 문제의 근본 원인을 찾은 거 같은데요...
setText를 할때, 실제 ListView에서 보이지 않는 Item에도 setText로 직접적으로 데이터를 넣으니
문제가 발생한 거 같습니다.
이에 해결책으로, 해당 Item이 화면에 보이는지 안 보이는지 확인하여 보일 때만 setText를 넣어주는 걸로 하니
제대로 동작하였습니다.
이는 위 본문 문제점 아래 부분에 해당합니다.
-----
헌데, 이상하게 제가 setText를 1번 행에 했다고 한다면.. 저~ 5번 행에서도 동일한 text가 적용되 보이게 됩니다.
하지만 실제 데이터를 읽어보면 원래 데이터가 제대로 저장 돼 있습니다. 보이기만 그렇게 보이더라구요..;;
심지어는 invisible 상태의 TextView가 값자기 보이는 경우도 있습니다.
--------
그런데 왜.. 안 보이는 영역에 setText를 하면 문제가 될 수 있는지 모르겠습니다.
해당 Item 객체가 생성 안 된 것도 아니구요..
invalidate() 함수 같은 경우는 View 클래스에서 사용하지 않으면 바로 화면에 갱신이 안 된다고는 들었습니다.