CursorAdapter?
- cursor를 사용하여 AdapterView에 데이터 표시
- cursor를 Adapter에 직접 전달
- 테이블에 반드시 _id컬럼이 만들어져 있어야 함
SimpleCurosrAdapter 사용
- 기본 제공 Adapter
- 안드로이드 제공 기본 레이아웃을 사용하여 cursor 데이터 출력
SimpleCursorAdpater adapter = new SimpleCursorAdapter(
/* context, MainActivity안에 있다면 this로 MainActivity 자신을 넣어주면 됨
MainActivity가 context를 상속받은 클래스이기 때문에 context 역할을 함 */
this,
android.R.layout.simple_list_item_1,
// DB 검색 결과
cursor,
// 표시할 컬럼
new String[] { ContactDBHelper.COL_NAME },
// 기본 레이아웃에 포함되어 있는 뷰 아이디
new int[] { android.R.id.text1 },
CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER);
SimpleCurosrAdapter 사용 예시
ListView listview = null;
ContactDBHelper helper;
Cursor cursor; // 멤버로 선언! cursor가 adapter에 직접 연결되기 때문에 cursor가 사라지면 어댑터 화면 못 만듦
SimpleCursorAdapter adapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_all_contacts);
lvContacts = (ListView)findViewById(R.id.lvContacts);
helper = new ContactDBHelper(this);
adapter = new SimpleCursorAdapter (this, android.R.layout.simple_list_item_1,
/* onCreate이므로 Activity가 만들어질 때 전체화면 읽어내고 그 이후 실행 x
cursor를 일단 비워두고 내용을 채우는 작업은 onResume에서 */
null,
new String[] { ContactDBHelper.COL_NAME }, new int[] { android.R.id.text1 },
CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER);
lvContacts.setAdapter(adapter);
} // 이 시점까지 화면에 보여지는 것 x
@Override
protected void onResume() { // 화면에 보이기 직전에 호출
super.onResume();
// DB에서 데이터를 읽어와 Adapter에 설정
SQLiteDatabase db = helper.getReadableDatabase();
cursor = db.rawQuery("select * from " + ContactDBHelper.TABLE_NAME, null);
adapter.changeCursor(cursor); // null로 되어 있는 cursor항목을 지금 얻은 cursor로 채우기
helper.close();
// cursor를 close시키지 않는 이유는 cursor가 닫히면 화면에 있는 연결 정보가 날아가기 때문
}
@Override
protected void onDestroy() { // Activity가 종료(제거)될 때 호출
super.onDestroy();
// cursor 사용 종료
if (cursor != null) cursor.close();
}
📍 swapCurosr
// 기존 cursor를 close하지 않음 - 검색 등 일시적으로 커서를 바꾸고자 할 때 사용
oldCursor = Adapter.swapCursor(new Cursor)
❗ cursor 값을 초기에는 null로 설정 - 화면이 열릴 때 데이터를 가져오기 위해
❗ CurosrAdapter.changeCursor(Cursor cursor) - 현재 Adapter에 설정되어 있는 cursor를 close한 후 매개변수 cursor로 Adapter 재설정
❗ 사용 중에는 cursor close하면 안됨 - cursor를 close하면 데이터 사용 불가
ListView 데이터 변경 시 화면 갱신
- 선택한 항목 확인은 id 사용 - 테이블의 _id와 일치
- onItemLongClick, onItemClick의 마지막 매개변수
onItemLongClick(AdapterView<?> adapterView, View view, int position, long id) onItemClick(AdapterView<?> adapterView, View view, int position, long id)
- onItemLongClick, onItemClick의 마지막 매개변수
- 갱신 - DB 변경 후 DB를 새로 읽어온 cursor로 Adpater의 cursor 변경
커스텀 CursorAdapter 사용
CursorAdapter를 사용하여 Custom View를 표시하는 경우
- ListView 각 항목을 표시하는 layout(xml) 정의
- CursorAdapter 상속 클래스 작성
- 생성자
- newView() - 기존 커스텀 Adapter의 getView()에서 custom view를 생성하는 역할 부분 -> LayoutInflater를 사용하여 ListView에 표시할 layout 객체 생성
- bindView() - newView()에서 생성한 layout의 내부 view에 cursor의 데이터를 결합하여 실제 view의 내용을 채움
- ListView에 커스텀 cursor adapter 설정
커스텀 CursorAdapter 사용 예시
public class MyCursorAdapter extends CursorAdapter { // CursorAdapter 상속
LayoutInflater inflater;
int layout;
public MyCursorAdapter(Context context, int layout, Cursor c) {
super(context, c, CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER);
this.inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
this.layout = layout;
}
// newView는 view에 데이터 결합할 때마다 호출
// newView는 화면에 보이는 view개수 만큼만 호출 (스크롤을 내리면 가려지는 뷰를 재사용)
@Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
View view = inflater.inflate(layout, parent, false);
ViewHolder holder = new ViewHolder();
view.setTag(holder);
return view;
}
// bindView는 view를 만들 때마다 호출
@Override
public void bindView(View view, Context context, Cursor cursor) {
// 한 번이라도 view가 사용이 되었다면 view의 holder안에 findViewById로 찾아놓은 요소들이 있음
ViewHolder holder = (ViewHolder) view.getTag();
if (holder.tvContactName == null) {
holder.tvContactName = view.findViewById(R.id.tvContactName);
holder.tvContactPhone = view.findViewById(R.id.tvContactPhone);
}
holder.tvContactName.setText(cursor.getString(cursor.getColumnIndex(ContactDBHelper.COL_NAME)));
holder.tvContactPhone.setText(cursor.getString(cursor.getColumnIndex(ContactDBHelper.COL_PHONE)));
}
// 정적멤버변수는 한 번 값을 정해두면 그 값을 유지되어서 지속적으로 사용 가능
static class ViewHolder {
TextView tvContactName;
TextView tvContactPhone;
// 기본적으로 static 클래스 멤버는 null로 초기화되지만 명시적으로
public ViewHolder() {
tvContactName = null;
tvContactPhone = null;
}
}
}
❗ 생성자에서 매개변수로 전달받은 커서 정보를 부모 클래스에 넣으면 newView()나 bindView()의 매개변수로 자동으로 들어감 (따로 멤버로 보관할 필요가 x) (context도 마찬가지)
- ListView에서 view가 필요할 때마다 newView로 view 생성
- 이 view에 데이터를 결합할 때 bindView가 호출이 되면서 생성된 view가 매개변수로 들어옴
'프로그래밍 > Android' 카테고리의 다른 글
[Android] 안드로이드 SQlite 사용 (0) | 2021.09.11 |
---|