안드로이드 개발 질문/답변
(글 수 45,052)
안녕하세요.
안드로이드를 공부하고 있는 대학생입니다.
현재 리스트 뷰를 DB와 연동하여 다음과 같이 구성하려고 합니다.
[list view 구조]
[DB 연결 구조]
/*mrg_row.xml*/
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<TextView android:id="@+id/mgr_row_subject"
android:textSize="20dip"
android:layout_width="60dip"
android:layout_height="wrap_content"/>
<LinearLayout
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:id="@+id/mgr_row_item">
</LinearLayout>
</LinearLayout>
/* mrg.java */
.
.
.
//row에서 Item에 해당되는 LinearLayout 안에 textView를 동적으로 추가하는 함수
public void appendRowTextView(LinearLayout parentLinearLayout, String szDefaultStr)
{
TextView Text = new TextView(this);
Text.setText(szDefaultStr);
LinearLayout.LayoutParams paramText = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.WRAP_CONTENT,
LinearLayout.LayoutParams.WRAP_CONTENT);
parentLinearLayout.addView(Text, paramText);
}
.
.
.
//ListView 데이터를 채우는 함수
private void fillData() {
// TODO Auto-generated method stub
Cursor cursor = m_clsDbHelper.fetchAllNotes();
startManagingCursor(cursor);
String[] from = new String[] { DbAdapter.KEY_WORD, DbAdapter.KEY_ITEM1, DbAdapter.KEY_ITEM2, DbAdapter.KEY_ITEM3, DbAdapter.ITEM4 };
int[] to = new int[] { R.id.mgr_row_title, R.id.mgr_row_items,R.id.mgr_row_items,R.id.mgr_row_items,R.id.mgr_row_items };
CustomCursorAdapter items =
new CustomCursorAdapter(this, R.layout.mrg_row, cursor, from, to);
setListAdapter(items);
}
//FillData시 DB 내용을 바인딩하는 함수
// SimpleCursorAdapter custom
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
if(view instanceof LinearLayout)
{//R.id.mgr_row_items
if(((LinearLayout)view).getId() == R.id.mgr_row_item)
{
String arrItem = cursor.getString(columnIndex);
if(arrItem.length() > 0)
{
String[] splitString = arrItem.split("/");
for(int i = 0 ; i < splitString.length; i++)
{
if(splitString[i].length() > 0)
{
appendRowTextView((LinearLayout)view, splitString[i]);
}
}
}
return true;
}
}
return false;
}
}/*class CustomViewBinder*/
} /*class CustomCursorAdapter*/
그림과 같이 구현하기 위하여 simplecursoradapter를 상속받아 오버라이딩하였습니다.
첫번째 문제점은 이렇게 구현했을때 listView의 mrg_row.xml의 최상위 view 인 LinearLayout 속성에 android:layout_height="wrap_content"를 주었음에도 불구하고 동적으로 View를 추가할때 맞춰서 row의 행 높이가 자동 조절이 안됩니다.
subject의 크기에 맞춰서 listview의 row높이가 결정되고 그안에서 스크롤이 되네요.
ItemAdd Intent를 호출했다가 다시 돌아오면 높이가 제대로 맞춰집니다.
ListView의 Row 크기를 재조정하는 함수를 찾아볼수가 없는데 이를 어떻게 해결해야 하는지 궁금합니다.
두번째 문제는 위 문제에서 스크롤을 상 하로 계속 하다보면 TextView 아이템이 늘어나더군요
그래서 디버깅으로 Textview를 동적으로 추가하는 appendRowTextView 함수에 breaking point를 걸어봤더니
스크롤을 하다보면 저절로 이 함수를 호출하더군요.
이클립스에서는 호출 스택을 보여주는 창을 못찾아서 누가 호출했는지도 모르겠네요.
스크롤 뷰의 업데이트가 호출이 되면 자동으로 등록된 Adapter를 호출하는 듯 싶은데, 이 호출 시점이 언제인지 궁금합니다. 또한 이렇게 저절로 호출이 되었을 경우 동적으로 생성된 아이템들을 제거하고 다시 생성 해야하는지 조언을 좀 해주시면 감사하겠습니다.
세번째 질문은 CustomViewBinder 에 대한 질문입니다.
public boolean setViewValue(View view, Cursor cursor, int columnIndex) 이 함수에서 columindex가 하는 역할을 잘 모르겠습니다.
CustomCursorAdapter(this, R.layout.wordmrgpage_row, cursor, from, to) 등록할때
view = to , cursor = cursor, 이렇게 페어로 들어오는 것은 알겠습니다.
하지만 from으로 들어가는 데이터는 string[]이고, columindex은 int형 변수라서 columindex값이 from과 매핑된다고 생각하고 위와 같이 구현했더니 생각했던 결과와 사뭇 다른 듯 싶습니다.
리스트뷰가 제대로 동작을 안해서 그런건지 Adapter의 구현이 잘못된 건지좀 봐주시면 감사하겠습니다.
부분적으로도 좋으니 많은 댓글 부탁드립니다. _꾸벅
안드로이드를 공부하고 있는 대학생입니다.
현재 리스트 뷰를 DB와 연동하여 다음과 같이 구성하려고 합니다.
[list view 구조]
[DB 연결 구조]
/*mrg_row.xml*/
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<TextView android:id="@+id/mgr_row_subject"
android:textSize="20dip"
android:layout_width="60dip"
android:layout_height="wrap_content"/>
<LinearLayout
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:id="@+id/mgr_row_item">
</LinearLayout>
</LinearLayout>
/* mrg.java */
.
.
.
//row에서 Item에 해당되는 LinearLayout 안에 textView를 동적으로 추가하는 함수
public void appendRowTextView(LinearLayout parentLinearLayout, String szDefaultStr)
{
TextView Text = new TextView(this);
Text.setText(szDefaultStr);
LinearLayout.LayoutParams paramText = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.WRAP_CONTENT,
LinearLayout.LayoutParams.WRAP_CONTENT);
parentLinearLayout.addView(Text, paramText);
}
.
.
.
//ListView 데이터를 채우는 함수
private void fillData() {
// TODO Auto-generated method stub
Cursor cursor = m_clsDbHelper.fetchAllNotes();
startManagingCursor(cursor);
String[] from = new String[] { DbAdapter.KEY_WORD, DbAdapter.KEY_ITEM1, DbAdapter.KEY_ITEM2, DbAdapter.KEY_ITEM3, DbAdapter.ITEM4 };
int[] to = new int[] { R.id.mgr_row_title, R.id.mgr_row_items,R.id.mgr_row_items,R.id.mgr_row_items,R.id.mgr_row_items };
CustomCursorAdapter items =
new CustomCursorAdapter(this, R.layout.mrg_row, cursor, from, to);
setListAdapter(items);
}
//FillData시 DB 내용을 바인딩하는 함수
// SimpleCursorAdapter custom
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
if(view instanceof LinearLayout)
{//R.id.mgr_row_items
if(((LinearLayout)view).getId() == R.id.mgr_row_item)
{
String arrItem = cursor.getString(columnIndex);
if(arrItem.length() > 0)
{
String[] splitString = arrItem.split("/");
for(int i = 0 ; i < splitString.length; i++)
{
if(splitString[i].length() > 0)
{
appendRowTextView((LinearLayout)view, splitString[i]);
}
}
}
return true;
}
}
return false;
}
}/*class CustomViewBinder*/
} /*class CustomCursorAdapter*/
그림과 같이 구현하기 위하여 simplecursoradapter를 상속받아 오버라이딩하였습니다.
첫번째 문제점은 이렇게 구현했을때 listView의 mrg_row.xml의 최상위 view 인 LinearLayout 속성에 android:layout_height="wrap_content"를 주었음에도 불구하고 동적으로 View를 추가할때 맞춰서 row의 행 높이가 자동 조절이 안됩니다.
subject의 크기에 맞춰서 listview의 row높이가 결정되고 그안에서 스크롤이 되네요.
ItemAdd Intent를 호출했다가 다시 돌아오면 높이가 제대로 맞춰집니다.
ListView의 Row 크기를 재조정하는 함수를 찾아볼수가 없는데 이를 어떻게 해결해야 하는지 궁금합니다.
두번째 문제는 위 문제에서 스크롤을 상 하로 계속 하다보면 TextView 아이템이 늘어나더군요
그래서 디버깅으로 Textview를 동적으로 추가하는 appendRowTextView 함수에 breaking point를 걸어봤더니
스크롤을 하다보면 저절로 이 함수를 호출하더군요.
이클립스에서는 호출 스택을 보여주는 창을 못찾아서 누가 호출했는지도 모르겠네요.
스크롤 뷰의 업데이트가 호출이 되면 자동으로 등록된 Adapter를 호출하는 듯 싶은데, 이 호출 시점이 언제인지 궁금합니다. 또한 이렇게 저절로 호출이 되었을 경우 동적으로 생성된 아이템들을 제거하고 다시 생성 해야하는지 조언을 좀 해주시면 감사하겠습니다.
세번째 질문은 CustomViewBinder 에 대한 질문입니다.
public boolean setViewValue(View view, Cursor cursor, int columnIndex) 이 함수에서 columindex가 하는 역할을 잘 모르겠습니다.
CustomCursorAdapter(this, R.layout.wordmrgpage_row, cursor, from, to) 등록할때
view = to , cursor = cursor, 이렇게 페어로 들어오는 것은 알겠습니다.
하지만 from으로 들어가는 데이터는 string[]이고, columindex은 int형 변수라서 columindex값이 from과 매핑된다고 생각하고 위와 같이 구현했더니 생각했던 결과와 사뭇 다른 듯 싶습니다.
리스트뷰가 제대로 동작을 안해서 그런건지 Adapter의 구현이 잘못된 건지좀 봐주시면 감사하겠습니다.
부분적으로도 좋으니 많은 댓글 부탁드립니다. _꾸벅
2010.08.09 15:39:12
그냥 가자님 감사합니다.
2번의 답변에서 getView를 이용하라 하셨는데 getView가 SimpleCursorAdapter의 portected 메소드를 말씀하시는 것이 맞는건가요?
안드로이드 프로그래밍 경험이 적어서 이 Getview의 역할과 기능, 호출 순서에 대해서 잘 모르니 수정할 방법이 딱히 떠오르지 않네요.ㅠ
getView는 어디서 봐야 잘 나와있나요?
추가로 getView를 잘 몰라서 그러는지 모르겠지만, adapter를 등록하면 처음에는 아답터에서 모두 로드 해서 처리하는 줄 알았으나, 실제로 그러지 않는 듯 싶네요. 아마도 스크롤하면서 생기는건 화면에 필요한 만큼만 로드를 해놓고 스크롤 되면서 필요한 정보를 추가로 로드를 하기에 다음과 같이 아답터의 등록함수가 호출되는 거 같습니다.
그렇다면 모든 아답터에서 필요한 정보를 얻어갈때 이전에 있던 정보는 반환하는 시스템이 될텐데 이 반환하는 시점의 함수가 존재하진 않나요? 말씀하신것 처럼 반환할때 추가된 TextView를 제거해주면 될 것 같기도 해서요
2. getView에서 contentView가 Null이면 super.getView를 통해서 View를 가져와서 리턴하시고,
null이 아니면 LinearLayout 비우고 다시 넣는 쪽으로 만들어 보시는게 좋을 것 같습니다.
(이건 될지 모르겠는데 contentView가 null이 아니면 super.getView에서 contentView 부분을 null로 해서 받아보세요)
*수정하였습니다.
3. columnIndex는 글쓴님께서 생각하시는것 처럼 cursor의 Column인덱스가 맞습니다.
우리는 컬럼명(String[])으로 주었기 때문에 여기서 쓰기쉽게 Index를 찾아 놓은거죠.
SimpleCursorAdapter에 보면 findColumns라는 함수로 인덱스를 추출하는 부분이 나옵니다.