위잿의 위치를 다룰 때에 레이아웃을 사용했다면, 위젯이나 다른 레이아웃에 데이터를 동적이로 표현해줄 때에는 컨테이너를 사용한다. 컨테이너는 데이터를 반복적으로 표시하는 용도로 사용하며, 대표적인 컨테이너로는 목록(List)을 화면에 출력할 때 사용하는 리사이클러뷰(RecyclerView)가 있다.
가장 많이 사용되는 것이 리사이클러뷰이고, 가장 복잡한 것도 리사이클러뷰이다.
컨테이너는 레이아웃과는 다르게 내부 요소의 위치를 결정할 수 있는 속성이 없으므로 컨테이너를 사용할 때는 다른 레이아웃을 컨테이너 안에 삽입해서 사용한다.
리사이클러뷰는 레이아웃 매니저를 이용하면 간단한 코드만으로 리스트를 그리드로 바꿀수도 있다.
리사이클러뷰처럼 목록을 표시하는 컨테이너들은 표시될 데이터와 아이템 레이아웃을 어댑터에서 연결해주므로 어댑터에서 어떤 아이템 레이아웃을 사용하느냐에 따라 표시되는 모양을 다르게 만들 수 있다.
화면 구성하기
1. activity_mai.xml에서 팔레트- Containers-RecyclerView를 드래그 해서 UI 편집기에 가져다 놓는다.
2. 리사이클러뷰의 id를 ‘recyclerView’라고 입력한다.
3. 레이아웃(ConstraintLayout / LinearLayout등)의 상하좌우를 모두 연결한다.
4. 여러개의 정보를 하나의 아이템에 보여줘야하니, 아이템의 레이아웃을 레이아웃 파일로 직접 생성하여 사용한다. [app]-[res]-[layout]에서 마우스 우클릭 [New]-[Layout Resource File]
5. File name에 ‘contact_row’를, Root element에 ‘LinearLayout’을 입력하고 [OK]를 클릭해서 파일을 생성한다. 다른 값은 건드리지 않는다. 파일명은 헝가리안 표기법을 사용하지 않는다.
6. contact_row.xml 파일을 열어서 컴토넌트 트리의 최상위 레이아웃이 리니어 레이아웃인 것을 확인한다.
7. x표시의 닫기 아이콘이 필요하므로, [app]-[res]에서 마우스 우클릭 [New]-[Vector Asset]
8. Name을 ‘ic_delete’로, Clip Art에는 clear로 검색하여, 하기 아이콘을, size는 48dp, color는 빨간색으로 설정하여 Next를 누르고, [app]-[res]-[drawble]에서 방금 생성한 파일을 확인한다.
9. 하기 코드를 참고한다.
코드:
<?xml version="1.0" encoding="utf-8"?> xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="#00BCD4" android:orientation="horizontal"> <androidx.cardview.widget.CardView android:id="@+id/cardView" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_marginLeft="10dp" android:layout_marginTop="10dp" android:layout_marginRight="10dp" android:layout_marginBottom="5dp" app:cardCornerRadius="5dp" app:cardElevation="5dp"> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="horizontal"> <LinearLayout android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="4" android:orientation="vertical"> <TextView android:id="@+id/txtName" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginLeft="10dp" android:layout_marginTop="15dp" android:text="이름" android:textSize="26sp" /> <TextView android:id="@+id/txtPhone" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_margin="10dp" android:text="전화번호" android:textSize="26sp" /> </LinearLayout> <ImageView android:id="@+id/imgDelete" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="10dp" android:layout_marginRight="10dp" android:src="@drawable/ic_baseline_close_24" /> </LinearLayout> </androidx.cardview.widget.CardView> </LinearLayout> |
데이터 정의하고 가상 데이터/어뎁터 만들기
리사이클러뷰는 리사이클러뷰어댑터라는 메서드 어댑터를 사용해서 데이터를 연결한다. 복잡한 구조이며, 상속이 필요한다. 상속을 하면 어댑터와 관련된 대부분의 기능을 사용할 수 있고 추가로 필요한 몇 개의 요소만 개발자가 직접 구현한다.
리사이클러뷰어댑터는 개별 데이터에 대응하는 뷰홀더 클래스를 사용한다. 상속하는 리사이클러뷰어댑터에 뷰홀더 클래스를 제네릭으로 지정해야 하므로, 뷰홀더 클래스를 먼저 만들고 나서 어댑터 클래스를 생성하는 것이 더 편하다.
상속받는 Adapter 클래스에 제네릭 뷰홀더를 지정해두면, Implement Methods로 코드를 자동 완성할 때에 자동 완성된 메서드 중 하나가 파라미터 타입에 제네릭으로 지정해둔 뷰홀더를 사용한다.
class 커스텀 어댑터 extends RecyclerView.Adapter<여기에 사용할 뷰홀더 지정>{ …. override void onBindViewHolder(뷰홀더, 아이템 위치){ } } |
어댑터를 먼저 만들 경우에는 뷰홀더 자리에 안드로이드에서 제공하는 타입이 입력되기 때문에 코드를 한 번 더 수정해야 한다.
뷰홀더 클래스도 기본 기능이 이미 만들어져 있는 ViewHolder 클래스를 상속받아서 만든다. 뷰홀더 클래스는 아이템 레이아웃을 포함하고 있는데, 1,000개의 데이터가 있다고 가정했을 때 이것을 모두 화면에 그리기 위해서 1,000개의 아이템 레이아웃을 생성하면 시스템 자원이 낭비되고, 심각할 경우 앱이 종료될 수도 있다.
뷰홀더는 현재 화면에 보여지는 개수만큼만 생성되고 목록이 위쪽으로 스크롤 될 경우 가장 위의 뷰홀더를 아래에서 재사용한 후 데이터만 바꿔주기 때문에 앱의 효율이 향상된다.
1. [app] - [java] - [기본 패키지명]에서 마우스 우클릭 [New]-[package], 이름을 Adapter로 정해준다. 그리고 마우스 우클릭 [New]-[ [javaclass], 이름을 ContactAdapter로 정해준다.
2. class ContactAdapter를 생성한 뒤, class ViewHolder를 추가로 작성한다. ContactAdapter 블록 안에 작성해야하고, 바로 아래 작성하는 것이 보기에 편하다.
class ContactAdapter{ class ViewHolder{ } } |
3. ViewHolder 클래스에 RecyclerView의 ViewHolder를 상속받는다.
4. ViewHolder에 빨간색 밑줄이 생기는 데 생성자에 1개의 값이 필수로 입력되야 하기 때문이다. 빨간 전구를 클릭하여 생성자를 만든다.
이 클래스에서는 contact_row.xml화면에서 있는 뷰를 연결시킨다.
5. 생성자 안에다가 화면과 연결시키는 코드를 작성한다.
public class ViewHolder extends RecyclerView.ViewHolder{
TextView txtName;
TextView txtPhone;
ImageView imgDelete;
CardView cardView;
public ViewHolder(@NonNull View itemView) {
super(itemView);
txtName = itemView.findViewById(R.id.txtName);
txtPhone = itemView.findViewById(R.id.txtPhone);
imgDelete = itemView.findViewById(R.id.imgDelete);
cardView = itemView.findViewById(R.id.cardView);
cardView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
// 카드뷰를 클릭하면 처리할 코드 작성.
// 1. 유저가 몇번째 행을 클릭했는지, 인덱스로 알려준다.
int index = getAdapterPosition();
// 2. 이 인덱스에 저장되어있는 데이터를 가져온다.
Contact contact = contactList.get(index);
// 3. 아이디, 이름, 전화번호를 , 수정하는 화면으로 데이터를 넘겨준다.
Intent intent = new Intent(context, EditActivity.class);
intent.putExtra("contact", contact);
context.startActivity(intent);
}
});
imgDelete.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
// 엑스이미지 누르면, 해당 주소록 삭제하도록 개발!
// 1. 어떤 행을 눌렀는지 정보를 얻어온다. 인덱스로.
deleteIndex = getAdapterPosition();
// 3. 알러트 다이얼로그를 띄운다.
AlertDialog.Builder alert = new AlertDialog.Builder(context);
alert.setTitle("주소록 삭제");
alert.setMessage("정말 삭제하시겠습니까?");
alert.setPositiveButton("YES", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
DatabaseHandler db = new DatabaseHandler(context);
Contact contact = contactList.get(deleteIndex);
db.deleteContact(contact);
db.close();
contactList.remove(deleteIndex);
notifyDataSetChanged();
}
});
alert.setNegativeButton("NO", null);
alert.show();
}
});
}
}
}
contact_row.xml 화면은 액티비티가 아니라서 자동완성이 안된다. 여기서의 itemView는 contact_row.xml화면의 전체 LinearLayout이다. 그래서 각 뷰는 itemView안에 있다.
6. ViewHolder 내부의 코드가 실행되기 전에 어댑터 클래스 코드가 먼저 선행되어야 하므로 어댑터 클래스를 먼저 수정한다. 다음과 같이 ContactAdapter 코드는 RecyclerView의 Adapter를 상속받고 위에서 생성한 ViewHolder를 제네릭으로 지정한다.
public class ContactAdapter extends RecyclerView.Adapter<ContactAdapter.ViewHolder> { } |
어댑터 클래스의 기본 구성
어댑터가 정상적으로 동작하려면 미리 정의된 Holder 클래스를 제네릭으로 지정한 후 어댑터에 설계되어 있는 3개의 인터페이스를 반드시 구현해야한다.
class 어댑터: RecyclerView.Adapter<Holder>{ onCreateViewHolder() onBindViewHolder() getItemCount() } |
onCreateViewHolder(): 한 화면에 그려지는 아이템 개수만큼 레이아웃 생성.
onBindViewHolder(): 생성된 아이템 레이아웃에 값 입력 후 목록에 출력, 데이터에 있는 것을 화면에 실제로 표시하는 함수
getItemCount(): 목록에 보여줄 아이템의 개수
8. 추가된 코드의 맨 윗줄에 이 어댑터에서 사용할 데이터 목록 변수를 선언한고, 생성자를 만들어준다.
Context context: 해당 변수가 있어야 어떤 액티비티의 소속인지 알려준다.
List<Contact> contactList는 MainActivity에서 데이터를 넘겨받을 것이다.
9. 리사이클러뷰에서 사용할 데이터의 총 개수를 리턴하는 getItemCount() 메서드부터 구현한다.
@Override public int getItemCount() { return contactList.size(); } |
10. 이어서 onCreateViewHolder() 메서드를 구현한다. 스마트폰의 한 화면에 보이는 개수만큼 안드로이드가 이 메서드를 호출한다. 한 화면에 여덟 줄이 보이면 여덟번 호출된다. 액티비티와는 다르게 어댑터에서 사용하는 바인딩인 inflate 메서드는 3개의 파라미터가 사용된다.
inflate란?
안드로이드에서 inflate의 정의는 xml에 표기된 레이아웃들을 메모리에 객체화 시키는 행동이다. 쉽게 말해서, XML 코드들을 객체화 해서 코드에 사용하기 위함이다.
기본적으로 안드로이드에서 화면(Activity 단위)을 하나 만들면 소스코드 하나와 화면을 구성하는 XML하나 이렇게 2개가 생성된다. 이때, setContentView() 함수가 바로 자동으로 만들어진 xml을 객체화 시키는 Infalte 동작이다.
다른 화면을 구성하는 xml을 불러오고 싶다면, 자동으로 생성된 xml이 아닌 user가 추가적으로 만든 xml을 객체화 시키기 위해서는 inflate과정이 필요하다.
inflate(inflater,paren,attachToRoot) 파라미터의 의미
inflater: 바인딩을 생성할 때 사용하는 인플레이터이다. 액티비티에서와는 다르게 LayoutInflater.from을 사용해서 생성해야한다. parent: 생성되는 바인딩이 속하는 부모 뷰(레이아웃)이다. attachToRoot: true일 경우 attach해야하는 대상으로 root를 지정하고 아래에 붙인다. false일 경우 뷰의 최상위 레이아웃의 속성을 기본으로 레이아웃이 적용된다. |
inflate 메서드는 3개의 파라미터가 사용된다.
inflate 사용전에 LayoutInflater.from을 먼저 작성해주며, from에는 파라미터로 context가 전달돼야 하는데, 이는 안드로이드가 넘겨주는 parent에서 꺼낼수 있다.
inflate의 첫번째 파라미터로 어느 xml을 불러올지 경로를 지정해주고, 두번째는 parent를 그대로 사용하고, 세번째는 항상 false를 사용하면 된다. 그리고 다음 줄에서 생성된 바인딩을 ViewHolder클래스에 담아서 반환한다.
안드로이드는 이런 과정을 거쳐 전달된 ViewHolder 클래스를 메모리에 저장했다가 요청이 있을 때마다 꺼내서 사용한다.
11. 생성된 뷰홀더를 화면에 보여주는 onBindViewHolder() 메서드를 구현한다. 먼저 리스트에 있는 contactList에 현재 위치에 해당하는 Contact를 하나 꺼내 contact 변수에 저장한 후 뷰홀더에 전달한다.
Contact contact = contactList.get(position);
-> 한 행마다 하나의 데이터이기 때문에, 행마다 연결시켜야한다. 행 하나에 필요한 데이터
-> position: 위치, 안드로이드 프레임 워크, 자체에서 알아서 가져온다.
holder.txtName.setText(contact.name);
holder.txtPhone.setText(contact.phone);
-> ContactAdapter.ViewHolder의 변수 holder: 화면
-> ViewHolder 클래스에 있는 txtName과 txtPhone.
MainActivity.java에서 어댑터 사용하기
지금까지 생성한 레이아웃과 소스코드를 MainActivity.java에서 모두 연결한다.
1. 리사이클러뷰, 어댑터, 데이터를 담는 contactList변수를 먼저 선언해준다. 이 셋중에 하나라도 없으면, 리사이클러뷰를 화면에 표시 못한다.
RecyclerView recyclerView; ContactAdapter adapter; ArrayList<Contact> contactList; |
2. setContentView 메서드 아래에 먼저 사용할 데이터를 생성하는 코드를 추가한다.
recyclerView = findViewById(R.id.recyclerView); recyclerView.setHasFixedSize(true); recyclerView.setLayoutManager(new LinearLayoutManager(MainActivity.this)); adapter = new ContactAdapter(MainActivity.this, contactList); |
리사이클러뷰 설정을 먼저 한다. 설정이 끝나면 데이터랑 연결한다.
3. 어댑터를 객체 생성하고, 화면/contact리스트는 DB에서 가져와야한다. DB가 있는지 DatabaseHandler.java 가서 확인해본다.
4. 데이터가 없으면, 하기 코드를 작성해준다.
5. 어댑터에 DB를 연결해준다.
recyclerView = findViewById(R.id.recyclerView); recyclerView.setHasFixedSize(true); recyclerView.setLayoutManager(new LinearLayoutManager(MainActivity.this)); contactList = db.getAllContacts(); adapter = new ContactAdapter(MainActivity.this, contactList); recyclerView.setAdapter(adapter); |
6. 이러면, 화면에서 새로운 데이터를 추가했을 때, 바로 반영이 되지 않는다. 다시 실행되는 함수 onResume() 에다가 반영된 데이터를 볼 수 있게 옮겨둔다.
onResume()은 appCompatActivity를 상속받은 MainActivity에서 오버라이딩을 한다.
@Override
protected void onResume() {
super.onResume();
// DB 에서 주소록 데이터를 모두 가져와서, 리사이클러뷰에 표시한다.
DatabaseHandler db = new DatabaseHandler(MainActivity.this);
contactList = db.getAllContacts();
adapter = new ContactAdapter(MainActivity.this, contactList);
recyclerView.setAdapter(adapter);
db.close();
printDBData();
}
ContactAdapter 전체 코드
import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ImageView; import android.widget.TextView; import androidx.annotation.NonNull; import androidx.appcompat.app.AlertDialog; import androidx.cardview.widget.CardView; import androidx.recyclerview.widget.RecyclerView; import com.****.contactmanager.EditActivity; import com.****.contactmanager.R; import com.****.contactmanager.data.DatabaseHandler; import com.****.contactmanager.model.Contact; import java.util.List; public class ContactAdapter extends RecyclerView.Adapter<ContactAdapter.ViewHolder> { // 어댑터 클래스의 멤버변수와 생성자를 만들어 준다. Context context; List<Contact> contactList; int deleteIndex; public ContactAdapter(Context context, List<Contact> contactList) { this.context = context; this.contactList = contactList; } @NonNull @Override public ContactAdapter.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { View view = LayoutInflater.from(parent.getContext()) .inflate(R.layout.contact_row, parent, false); return new ContactAdapter.ViewHolder(view) ; } // 메모리에 있는 데이터(리스트) 를 화면에 표시하는 함수. @Override public void onBindViewHolder(@NonNull ContactAdapter.ViewHolder holder, int position) { Contact contact = contactList.get(position); holder.txtName.setText(contact.name); holder.txtPhone.setText(contact.phone); } @Override public int getItemCount() { return contactList.size(); } public class ViewHolder extends RecyclerView.ViewHolder{ TextView txtName; TextView txtPhone; ImageView imgDelete; CardView cardView; // 3. 생성자 안에다가, 연결시키는 코드를 작성한다. public ViewHolder(@NonNull View itemView) { super(itemView); txtName = itemView.findViewById(R.id.txtName); txtPhone = itemView.findViewById(R.id.txtPhone); imgDelete = itemView.findViewById(R.id.imgDelete); cardView = itemView.findViewById(R.id.cardView); cardView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { // 카드뷰를 클릭하면 처리할 코드 작성. // 1. 유저가 몇번째 행을 클릭했는지, 인덱스로 알려준다. int index = getAdapterPosition(); Log.i("MyContact", "몇번째 행 클릭했나?? " + index); // 2. 이 인덱스에 저장되어있는 데이터를 가져온다. Contact contact = contactList.get(index); // contact 안에 id, name, phone 다 들어있다. // 3. 아이디, 이름, 전화번호를 , 수정하는 화면으로 데이터를 넘겨준다. Intent intent = new Intent(context, EditActivity.class); intent.putExtra("contact", contact); // 데이터를 하나씩 보낼때 사용하는 방법 // intent.putExtra("id", contact.id); // intent.putExtra("name", contact.name); // intent.putExtra("phone", contact.phone); context.startActivity(intent); } }); imgDelete.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { // 엑스이미지 누르면, 해당 주소록 삭제하도록 개발! // 1. 어떤 행을 눌렀는지 정보를 얻어온다. 인덱스로. deleteIndex = getAdapterPosition(); // 3. 알러트 다이얼로그를 띄운다. AlertDialog.Builder alert = new AlertDialog.Builder(context); alert.setTitle("주소록 삭제"); alert.setMessage("정말 삭제하시겠습니까?"); alert.setPositiveButton("YES", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialogInterface, int i) { DatabaseHandler db = new DatabaseHandler(context); Contact contact = contactList.get(deleteIndex); db.deleteContact(contact); db.close(); contactList.remove(deleteIndex); notifyDataSetChanged(); } }); alert.setNegativeButton("NO", null); alert.show(); } }); } } } |
MainActivity 코드:
import androidx.appcompat.app.AppCompatActivity; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; import android.content.Intent; import android.os.Bundle; import android.util.Log; import android.view.View; import android.widget.Button; import com.****.contactmanager.adapter.ContactAdapter; import com.****.contactmanager.data.DatabaseHandler; import com.****.contactmanager.model.Contact; import java.util.ArrayList; public class MainActivity extends AppCompatActivity { RecyclerView recyclerView; ContactAdapter adapter; ArrayList<Contact> contactList; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Button btnAdd = findViewById(R.id.btnAdd); recyclerView = findViewById(R.id.recyclerView); recyclerView.setHasFixedSize(true); recyclerView.setLayoutManager(new LinearLayoutManager(MainActivity.this)); btnAdd.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Intent intent = new Intent(MainActivity.this, AddActivity.class); startActivity(intent); } }); } @Override protected void onResume() { super.onResume(); // DB 에서 주소록 데이터를 모두 가져와서, 리사이클러뷰에 표시한다. DatabaseHandler db = new DatabaseHandler(MainActivity.this); contactList = db.getAllContacts(); adapter = new ContactAdapter(MainActivity.this, contactList); recyclerView.setAdapter(adapter); db.close(); printDBData(); } |
DatabaseHandler 코드:
import android.content.ContentValues; import android.content.Context; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteOpenHelper; import android.util.Log; import androidx.annotation.Nullable; import com.****.contactmanager.model.Contact; import com.****.contactmanager.util.Util; import java.util.ArrayList; public class DatabaseHandler extends SQLiteOpenHelper { public DatabaseHandler(@Nullable Context context) { super(context, Util.DATABASE_NAME, null, Util.DATABASE_VERSION); } @Override public void onCreate(SQLiteDatabase sqLiteDatabase) { // 테이블 생성 String CREATE_CONTACT_TABLE = "create table " + Util.TABLE_NAME + "("+ Util.KEY_ID + " integer primary key, " + Util.KEY_NAME + " text, " + Util.KEY_PHONE + " text )"; Log.i("MyContact", "테이블 생성문 : " + CREATE_CONTACT_TABLE); sqLiteDatabase.execSQL(CREATE_CONTACT_TABLE); } @Override public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) { // 기존의 contact 테이블을 삭제하고, String DROP_TABLE = "drop table " +Util.TABLE_NAME; sqLiteDatabase.execSQL(DROP_TABLE, new String[]{Util.DATABASE_NAME}); // 새롭게 테이블을 다시 만든다. onCreate(sqLiteDatabase); } public void addContact(Contact contact){ // 데이터베이스를 가져온다. SQLiteDatabase db = this.getWritableDatabase(); // 테이블의 컬럼이름과 해당 데이터를 매칭해서 넣어준다. ContentValues values = new ContentValues(); values.put(Util.KEY_NAME, contact.name); values.put(Util.KEY_PHONE, contact.phone); // 데이터베이스에, 위의 데이터를 insert db.insert(Util.TABLE_NAME, null, values); // db를 닫아줘야 한다. db.close(); } // 주소록 데이터 가져오기: 1개의 주소록 데이터만 가져오기 : id로 가져오기 public Contact getContact(int id){ // 1. 데이터베이스를 가져온다. SQLiteDatabase db = this.getReadableDatabase(); // 2. 쿼리문 만든다. Cursor cursor = db.rawQuery("select * from contact where id = "+id, null); // Cursor cursor = db.rawQuery("select * from contact where id = ?", new String[]{""+id}); if(cursor != null){ cursor.moveToFirst(); } // DB 에 저장된 데이터를 메모리에다 만들어줘야, cpu가 처리할 수 있다. Contact contact = new Contact(cursor.getInt(0), cursor.getString(1), cursor.getString(2)); db.close(); return contact; } // - 주소록 데이터 전체 가져오기 public ArrayList<Contact> getAllContacts() { // 1. 데이터베이스를 가져온다. SQLiteDatabase db = this.getReadableDatabase(); // 2. 쿼리문 만든다. Cursor cursor = db.rawQuery("select * from contact", null); ArrayList<Contact> contactList = new ArrayList<Contact>(); if(cursor.moveToFirst()){ do{ Contact contact = new Contact(cursor.getInt(0), cursor.getString(1), cursor.getString(2)); contactList.add(contact); }while(cursor.moveToNext()); } db.close(); return contactList; } // 데이터 수정하는 함수 public void updateContact(Contact contact){ SQLiteDatabase db = this.getWritableDatabase(); db.execSQL("update contact set name = ? , phone = ? where id = ?" , new String[]{contact.name, contact.phone, contact.id+""}); db.close(); } public void deleteContact(Contact contact){ SQLiteDatabase db = this.getWritableDatabase(); db.execSQL("delete from contact where id = ?" , new String[]{ contact.id+""}); db.close(); } } |
'FrontEnd > Android 기초' 카테고리의 다른 글
[Android] ActionBar 이름 변경 방법 + 액션바에 Back 버튼 추가 (1) | 2022.07.19 |
---|---|
[Android] 메모: TODO (0) | 2022.07.19 |
[Android] SQLite3 데이터베이스 02: Create,Read,Update,Delete (0) | 2022.07.19 |
[Android] SQLite3 데이터베이스 01 (feat. SQLiteOpenHelper) (0) | 2022.07.19 |
[Android] TextWatcher 사용법(feat.addTextChangedListener) (0) | 2022.07.19 |