안드로이드 개발 질문/답변
(글 수 45,052)
안녕하세요.
안드로이드 공부하고있는 대학생입니다.
더운날씨에 모두 힘내시고, 질답 게시판으로 많은 도움을 받고 한창 열심히 공부를 열심히하고있네요.
감사드립니다.
이번에 궁금한점은 제가 SimpleCursorAdapter을 커스텀화 시켜서 아래의 구조를 구현했습니다
Lenearlayout에 들어가는 textview가 동적으로 1~n개가 들어가는 구조입니다.
코드상에서 textview를 생성하여 xml에 있는 Lenearlayout 에 add하는 방식입니다.
여기서 문제가 발생하는데요. 디버깅으로 확인결과 ListView에서 화면에 보여질 수 있는 것만 로드를 하더군요. 만약 화면을 스크롤하여 내리게 되면 밑에 필요한 정보를 그때그때 연결된 adapter를 통하여 데이터를 얻고 갱신하여 보여줍니다.
이 메커니즘을 이해하여 위와 같이 코딩을 하였습니다.
문제는 반환 메카니즘입니다. 이것은 어떻게 구현을 해야할 지 모르겠네요.
일반적으로 필요한 부분만 로드를 한다고하면, 안보이게 되는 불필요한 부분은 반환하는게 정상일거라 생각합니다. 하지만 제 코드에서 로그를 찍어보니 스크롤을 내렸다가 위로 올리니 row를 새로 생성하지 않고 있는것을 그대로 이용하더군요.
이러한 문제는 cursoradapter 문제가 아니라 모든 adapter가 view에 연동되었을때 코드상에서 view를 추가할때 발생할 수 있는 문제라 생각합니다.
원래 반환 메커니즘이 제가 생각한것이 맞는지 잘모르겠으나 반환이 된다면 어떻게 코딩을 해야 제가 생성한 TextView를 반환할 수 있는지 알려주시면 감사하겠습니다.
또한 제가 검색이 미흡해서 못찾아서 그러니, 혹시 Adater와 ListView를 연동했을때 각 상호 호출되는 함수의 순서 및 그 기능에 대하여 나온 자료를 가지고 계신분은 링크좀 부탁드리겠습니다..
제가 안드로이드 구조나 자세한 메커니즘을 다룬 책들을 보지 않아서 많은 경험자님들의 조언을 듣고싶습니다.
많은 댓글 부탁드립니다. 감사합니다^^
안드로이드 공부하고있는 대학생입니다.
더운날씨에 모두 힘내시고, 질답 게시판으로 많은 도움을 받고 한창 열심히 공부를 열심히하고있네요.
감사드립니다.
이번에 궁금한점은 제가 SimpleCursorAdapter을 커스텀화 시켜서 아래의 구조를 구현했습니다
Lenearlayout에 들어가는 textview가 동적으로 1~n개가 들어가는 구조입니다.
코드상에서 textview를 생성하여 xml에 있는 Lenearlayout 에 add하는 방식입니다.
여기서 문제가 발생하는데요. 디버깅으로 확인결과 ListView에서 화면에 보여질 수 있는 것만 로드를 하더군요. 만약 화면을 스크롤하여 내리게 되면 밑에 필요한 정보를 그때그때 연결된 adapter를 통하여 데이터를 얻고 갱신하여 보여줍니다.
이 메커니즘을 이해하여 위와 같이 코딩을 하였습니다.
문제는 반환 메카니즘입니다. 이것은 어떻게 구현을 해야할 지 모르겠네요.
일반적으로 필요한 부분만 로드를 한다고하면, 안보이게 되는 불필요한 부분은 반환하는게 정상일거라 생각합니다. 하지만 제 코드에서 로그를 찍어보니 스크롤을 내렸다가 위로 올리니 row를 새로 생성하지 않고 있는것을 그대로 이용하더군요.
이러한 문제는 cursoradapter 문제가 아니라 모든 adapter가 view에 연동되었을때 코드상에서 view를 추가할때 발생할 수 있는 문제라 생각합니다.
원래 반환 메커니즘이 제가 생각한것이 맞는지 잘모르겠으나 반환이 된다면 어떻게 코딩을 해야 제가 생성한 TextView를 반환할 수 있는지 알려주시면 감사하겠습니다.
또한 제가 검색이 미흡해서 못찾아서 그러니, 혹시 Adater와 ListView를 연동했을때 각 상호 호출되는 함수의 순서 및 그 기능에 대하여 나온 자료를 가지고 계신분은 링크좀 부탁드리겠습니다..
제가 안드로이드 구조나 자세한 메커니즘을 다룬 책들을 보지 않아서 많은 경험자님들의 조언을 듣고싶습니다.
많은 댓글 부탁드립니다. 감사합니다^^
2010.08.11 17:30:04
ListView와 Adapter에서 기존 View를 재활용 하는 것은 맞는 이야기구요...
결국은 getView에 오면 contentView가 null이면 새로 만들어야 하는 것이고
contentView가 null이 아니면 기존 View를 재활용합니다.
보통 BaseAdapter를 바로 상속받아 커스텀하는 Adapter의 경우 getView에서 레이아웃을 inflate 하는 것으로 새 View를 생성합니다.
CursorAdapter를 상속 받아 커스텀하는 Adapter의 경우 inflate 한 새 View에다가 bindView를 거쳐 줘야 합니다.
그 과정을 그냥 super.getView() 형태로 얻을 수 있습니다.
그림을 보니까 리니어에 TextView가 동적인 숫자로 들어가는데...
필드를 매칭할때 저 리니어에 매칭하고 TextView를 추가하는 방법을 쓰는게 좋을 것 같습니다.
그리고 getView를 오버라이드 하셔서
널이 아닌 contentView가 왔을 때도 무조건 super.getView 받아서 그걸 리턴해주세요.
여기서 super.getView 하실때 contentView 부분을 null로 주세요. 그러면 아예 새로 만들겁니다. position값 기반으로요...
결국은 getView에 오면 contentView가 null이면 새로 만들어야 하는 것이고
contentView가 null이 아니면 기존 View를 재활용합니다.
보통 BaseAdapter를 바로 상속받아 커스텀하는 Adapter의 경우 getView에서 레이아웃을 inflate 하는 것으로 새 View를 생성합니다.
CursorAdapter를 상속 받아 커스텀하는 Adapter의 경우 inflate 한 새 View에다가 bindView를 거쳐 줘야 합니다.
그 과정을 그냥 super.getView() 형태로 얻을 수 있습니다.
그림을 보니까 리니어에 TextView가 동적인 숫자로 들어가는데...
필드를 매칭할때 저 리니어에 매칭하고 TextView를 추가하는 방법을 쓰는게 좋을 것 같습니다.
그리고 getView를 오버라이드 하셔서
널이 아닌 contentView가 왔을 때도 무조건 super.getView 받아서 그걸 리턴해주세요.
여기서 super.getView 하실때 contentView 부분을 null로 주세요. 그러면 아예 새로 만들겁니다. position값 기반으로요...
2010.08.11 18:09:43
아.. 제가 설명이 부족했나봅니다. 저거 구현은 simplecursoradapter 커스텀시켜 구현 했습니다. 작동은 잘 하고요, 근데 제가 알고싶은건 메모리에 할당된 객체들이 남아있어서 질문을 올렸습니다. 스크롤시 첫번재 row가 사라지면 이것은 제거를 해줘야하는게 맞는건지를 물어봤고, 만약 이게 제거가 된다고 하면 현재 제 코드에서는 이것을 반환하지 않는데 row에 할당된 독적인 객체들이 제거가 되도록 호출 함수를 오버라이드 할 필요성이 있어서 그에 대한 질문이였습니다.
getview의 경우 cursoradpater의 경우 bindview로 처리해야할 것 같은데, 저는 ViewBinder를 커스텀시켜서 이것을 아답터에서 사용하도록 코딩했습니다.
public class CustomCursorAdapter extends SimpleCursorAdapter
{
public CustomCursorAdapter(Context context, int layout, Cursor c,
String[] from, int[] to)
{
super(context, layout, c, from, to);
// TODO Auto-generated constructor stub
this.setViewBinder(new CustomViewBinder());
}
public class CustomViewBinder implements ViewBinder {
@Override
public boolean setViewValue(View view, Cursor cursor, int columnIndex)
{
// TODO Auto-generated method stub
// TODO 동적으로 할당하는 코드
}
}
위와 같이요. cursoradapter에서 ViewBind를 오버라이딩해도 호출 순서가 커스텀 뷰바인드를 호출하고 cursoradapter의 vewBind함수를 호출하더군요.
getview의 경우 cursoradpater의 경우 bindview로 처리해야할 것 같은데, 저는 ViewBinder를 커스텀시켜서 이것을 아답터에서 사용하도록 코딩했습니다.
public class CustomCursorAdapter extends SimpleCursorAdapter
{
public CustomCursorAdapter(Context context, int layout, Cursor c,
String[] from, int[] to)
{
super(context, layout, c, from, to);
// TODO Auto-generated constructor stub
this.setViewBinder(new CustomViewBinder());
}
public class CustomViewBinder implements ViewBinder {
@Override
public boolean setViewValue(View view, Cursor cursor, int columnIndex)
{
// TODO Auto-generated method stub
// TODO 동적으로 할당하는 코드
}
}
위와 같이요. cursoradapter에서 ViewBind를 오버라이딩해도 호출 순서가 커스텀 뷰바인드를 호출하고 cursoradapter의 vewBind함수를 호출하더군요.
2010.08.11 18:29:55
그냥 가자님 자꾸 질문드려 귀찮게 해서 죄송합니다. 제가 안드로이드 프로그래밍을 공부한지 얼마 안되서 이해가 잘 안되네요. 해당 게시물은 제가 cursoradatper 자료를 찾아볼때 봤습니다. 문제는 해당 댓글에 들어가는 map의 의미를 잘 모르겠더군요. 해당 map에 해당되는 변수도 잘 모르겠구요 mapping table을 말씀하시는 것 같은데 이게 구체적으로 어떻게 구성이 되는지 구조를 볼 수 가없어서 사용을 못하고있었습니다.ㅠ 마지막에 ViewGroup.OnHierarchyChangeListener로 어떻게 하라고 하는데 저는 도무지 응용이 안 되네요.
2010.08.11 18:41:00
일단 결론부터 말씀드리면 스크롤이나 ListView의 새로고침 할때 Item의 View가 지워지는 경우가 있습니다.
이때 ViewGroup (ListView도 ViewGroup을 상속 받았습니다.)의 OnHierarchyChangeListener가 호출됩니다.
그중에 View가 날아가는 이벤트는 아래 함수입니다.
public void onChildViewRemoved(View parent, View child) {}
저기의 child가 님이 찾는 바로 그 View입니다. 지워질때 날아가는 View죠...
만약 저 View가 GC (가비지 컬랙터)에 의해 지워지지 않아서 죽어난다고 하시믄
링크에 써 놓은대로 함수 구현하시면 됩니다.
단 이경우 SimpleCursorAdapter를 풀소스 다 배낀다 생각하고 긁어놓고 해야 합니다.
이때 ViewGroup (ListView도 ViewGroup을 상속 받았습니다.)의 OnHierarchyChangeListener가 호출됩니다.
그중에 View가 날아가는 이벤트는 아래 함수입니다.
public void onChildViewRemoved(View parent, View child) {}
저기의 child가 님이 찾는 바로 그 View입니다. 지워질때 날아가는 View죠...
만약 저 View가 GC (가비지 컬랙터)에 의해 지워지지 않아서 죽어난다고 하시믄
링크에 써 놓은대로 함수 구현하시면 됩니다.
단 이경우 SimpleCursorAdapter를 풀소스 다 배낀다 생각하고 긁어놓고 해야 합니다.
각 Row에 Custom하게 TextView를 넣고 싶으시다는건가요?
CustomAdapter를 만드시게 되면, Adapter를 상속받아서 구현을 하시게 될건데요.
거기서 getView라는 메서드를 Override할때 해당 row의 position과 View를 얻을 수 있습니다.
그래서 그 View에다가 원하는 형태의 layout을 집어넣을 수 있고요.
CustomAdapter만드는 소스들을 찾아보시면 도움이 될 듯 합니다.