일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
- ubuntu python
- graphQL
- flutter
- Android
- 안드로이드 디자인패턴
- 파이썬 크롤링
- dagger-hilt
- Data structure
- 유니티
- Dependency Injection
- Apollo GraphQL
- mvvm
- prisma
- LinkedList
- Design Pattern
- java
- unit test
- 안드로이드 테스트
- 자바
- Nexus GraphQL
- Android test
- Kotlin
- 안드로이드 mvp
- MVVM pattern
- 웹크롤링
- Apollo Server
- 안드로이드
- PYTHON
- 우분투 파이썬
- 자바기초
- Today
- Total
Hun's Blog
안드로이드 Room Database + Live Data 본문
참고
https://developer.android.com/training/data-storage/room?hl=ko
https://www.youtube.com/watch?v=jit8j4gblIk&list=PLxTmPHxRH3VXHOBnaGQcbSGslbAjr8obc&index=3
Room DataBase
SQLite에 대한 추상화 레이어를 제공하여 원활한 데이터베이스 액세스를 지원하는 동시에 SQLite를 완벽히 활용한다.
3가지 구성요소
1) 데이터베이스
:데이터베이스 홀더를 포함하며 앱의 지속적인 관계형 데이터에 대한 기본 연결을 위한 액세스 포인트 역할을 한다.
-> @Database로 주석처리 되어있다.
-> RoomDatabase를 상속받은 추상 클래스이다.
-> 인수가 0개인 추상 메서드를 포함하고 @Dao로 주석 처리된 클래스를 반환한다.
2) 항목
:데이터베이스 내의 테이블을 나타낸다.
3) DAO
: 데이터베이스에 액세스하는데 사용되는 메서드가 포함되어있는 인터페이스이다.
app - build.gradle
1
2
3
4
5
|
//Room
implementation 'androidx.room:room-runtime:2.2.5'
annotationProcessor 'androidx.room:room-compiler:2.2.5'
// LiveData
implementation "androidx.lifecycle:lifecycle-livedata:2.2.0"
|
activity_room.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
|
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".room.RoomActivity">
<EditText
android:id="@+id/add_edit"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:ems="10"
android:inputType="textPersonName"
android:hint="타이틀 입력"
app:layout_constraintEnd_toStartOf="@id/add_button"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/add_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="추가"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<EditText
android:id="@+id/update_id_edit"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:ems="10"
android:hint="아이디 입력"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toStartOf="@id/update_title_edit"
app:layout_constraintTop_toBottomOf="@id/add_edit"/>
<EditText
android:id="@+id/update_title_edit"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:ems="10"
android:hint="타이틀 입력"
app:layout_constraintEnd_toStartOf="@id/update_button"
app:layout_constraintStart_toEndOf="@id/update_id_edit"
app:layout_constraintTop_toBottomOf="@id/add_button" />
<Button
android:id="@+id/update_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="변경"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@id/add_button" />
<EditText
android:id="@+id/delete_edit"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:ems="10"
android:inputType="textPersonName"
android:hint="아이디 입력"
app:layout_constraintEnd_toStartOf="@id/delete_button"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/update_button" />
<Button
android:id="@+id/delete_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="삭제"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@id/update_button" />
<Button
android:id="@+id/clear_button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="전체삭제"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/delete_button" />
<TextView
android:id="@+id/result_text"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginStart="8dp"
android:layout_marginLeft="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:layout_marginRight="8dp"
android:layout_marginBottom="8dp"
android:text="TextView"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/clear_button" />
|
DataModel -> 항목
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
|
/**
* Room 에서 사용할 수 있는 Entity 가 되기위해서
* @Entity Annotation 추가
* */
@Entity
public class DataModel {
/**
* id = primaryKEY
* autoGenerate -> 자동으로 증가
* */
@PrimaryKey(autoGenerate = true)
private int id;
private String title;
// 생성자
public DataModel(String title){
this.title = title;
}
public void setTitle(String title) { this.title = title; }
public String getTitle() { return title; }
public int getId() { return id; }
public void setId(int id) { this.id = id; }
/**
* toString 재정의 -> 내용확인하기 위함
* */
@NonNull
@Override
public String toString() {
final StringBuffer sb = new StringBuffer("DataModel{");
sb.append("id=").append(id);
sb.append('}');
return sb.toString();
}
}
http://colorscripter.com/info#e" target="_blank" style="color:#e5e5e5text-decoration:none">Colored by Color Scripter
|
LocalDataBase -> 데이터베이스
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
/**
* Database 객체 -> abstract class , RoomDatabase 상속
* Database annotation -> Entity 클래스와 버전을 명시
**/
@Database(entities = {DataModel.class}, version = 1, exportSchema = false)
public abstract class LocalDatabase extends RoomDatabase {
/**
* 이 객체가 제공하는 Data Access Object
* AppDatabase 가 생성되고 TodoDAO 를 통해서 조작한다.
**/
public abstract DataModelDAO dataModelDAO();
}
http://colorscripter.com/info#e" target="_blank" style="color:#e5e5e5text-decoration:none">Colored by Color Scripter
|
DataModelDAO -> DAO
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
|
/**
* Data Access Object -> Todo Entity 에 접근하기 위한 인터페이스
* @Dao annotation 추가
* Todo 에서 어떤 동작을 할 것인지 정의한다.
* */
@Dao
public interface DataModelDAO {
/**
* Todo 라는 테이블에 여러 내용이 있을 것이다.
* Todo 의 모든 내용을 List 에 담는 getAll() 이라는 메소드가 필요하다.
* Query annotation -> 실제 sql query 를 사용할 수 있음
* LiveData<객체> -> 해당 객체는 관찰 가능한 객체가 된다.
**/
@Query("SELECT * FROM DataModel")
LiveData<List<DataModel>> getAll();
/**
* id로 데이터 찾기
* */
@Query("SELECT * FROM DataModel WHERE id = :mId")
DataModel getData(int mId);
/**
* Insert annotation -> 내용추가
**/
@Insert
void insert(DataModel dataModel);
/**
* Delete annotation -> 내용 삭제
**/
@Delete
void delete(DataModel dataModel);
/**
* id로 데이터를 찾고 입력받은 String 으로 타이틀을 변경
**/
@Query("UPDATE DataModel SET title =:mTitle WHERE id =:mId ")
void dataUpdate(int mId, String mTitle);
/**
* Clear All -> 리스트 전체삭제
**/
@Query("DELETE FROM DataModel")
void clearAll();
}
|
getAll 메소드에서 LiveData가 활용된다.
LiveData가 List<DataModel> 을 감싸고 있다.
액티비티에서 그 활용도를 알아볼 수 있다.
RoomActivity
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
|
public class RoomActivity extends AppCompatActivity {
//UI View
private EditText mAddEdit, mUpdateIdEdit, mUpdateTitleEdit, mDeleteEdit;
private TextView mResultTextView;
private Button mAddButton, mUpdateButton, mDeleteButton, mClearButton;
// Room Database
private LocalDatabase db;
private final String INSERT = "INSERT";
private final String UPDATE = "UPDATE";
private final String DELETE = "DELETE";
private final String CLEAR = "CLEAR";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_room);
mAddEdit = (EditText) findViewById(R.id.add_edit);
mUpdateIdEdit = (EditText) findViewById(R.id.update_id_edit);
mUpdateTitleEdit = (EditText) findViewById(R.id.update_title_edit);
mDeleteEdit = (EditText) findViewById(R.id.delete_edit);
mResultTextView = (TextView) findViewById(R.id.result_text);
mAddButton = (Button) findViewById(R.id.add_button);
mUpdateButton = (Button) findViewById(R.id.update_button);
mDeleteButton = (Button) findViewById(R.id.delete_button);
mClearButton = (Button) findViewById(R.id.clear_button);
/**
* LocalDatabase 객체 생성 -> db
* databaseBuilder(context, Database 객체, Database 명)
* Database 명의 파일이 실제로 생성 된다.
**/
db = Room.databaseBuilder(this, LocalDatabase.class, "test-db")
.build();
/**
* Database 를 관찰하고 변경이 감지될 때 UI 갱신
* 데이터베이스 db -> 데이터베이스 mDataModelDAO()
* -> getAll() 가져오는 List<DataModel> 객체는 관찰 가능한 객체 이므로
* -> observe 메소드로 관찰하고 변경이 되면 dataList 에 추가한다.
* 변경된 내용이 담긴 dataList 를 출력한다.
**/
/*
* 람다식 사용
* file -> project structure -> modules -> source compatibility, target compatibility -> 1.8
**/
db.dataModelDAO().getAll().observe(this, dataList -> {
mResultTextView.setText(dataList.toString());
});
/**
* Insert
* 데이터배이스 객체 . 데이터베이스 DAO . insert -> new DataModel (텍스트 추가)
**/
mAddButton.setOnClickListener(v -> {
/**
* AsyncTask 생성자에 execute 로 DataModelDAO 객체를 던저준다.
* 비동기 처리
**/
new DaoAsyncTask(db.dataModelDAO(),INSERT,0,"")
.execute(new DataModel(mAddEdit.getText().toString()));
});
/**
* Update
* 데이터베이스 -> getData(id) -> id 입력하여 DataModel 받아오기
* -> update(DataModel) 해당 데이터 업데이트
**/
mUpdateButton.setOnClickListener(v ->
new DaoAsyncTask(
db.dataModelDAO(),
UPDATE,
Integer.parseInt(mUpdateIdEdit.getText().toString()),
mUpdateTitleEdit.getText().toString()
).execute()
);
/**
* Delete
* 데이터베이스 -> getData(id) -> id 입력하여 DataModel 받아오기
* -> delete(DataModel) 해당 데이터 삭제
* */
mDeleteButton.setOnClickListener(v ->
new DaoAsyncTask(
db.dataModelDAO(),
DELETE,
Integer.parseInt(mDeleteEdit.getText().toString()),
""
).execute()
);
/**
* Clear
* 데이터베이스 -> allClear -> 리스트 전부 지움
* */
mClearButton.setOnClickListener(v ->
new DaoAsyncTask(db.dataModelDAO(),CLEAR,0,"").execute()
);
}
/**
* 비동기 처리 해주는 것은 dataModelDAO() 이다.
* InsertAsyncTask 생성자를 만들어 dataModelDAO() 객체를 받는다.
**/
private static class DaoAsyncTask extends AsyncTask<DataModel,Void,Void>{
private DataModelDAO mDataModelDAO;
private String mType;
private int mId;
private String mTitle;
private DaoAsyncTask (DataModelDAO dataModelDAO, String type, int id, String title) {
this.mDataModelDAO = dataModelDAO;
this.mType = type;
this.mId = id;
this.mTitle = title;
}
@Override
protected Void doInBackground(DataModel... dataModels) {
if(mType.equals("INSERT")){
}
else if(mType.equals("UPDATE")){
if(mDataModelDAO.getData(mId) != null){
mDataModelDAO.dataUpdate(mId,mTitle);
}
}
else if(mType.equals("DELETE")){
if(mDataModelDAO.getData(mId) != null) {
}
}
else if(mType.equals("CLEAR")){
mDataModelDAO.clearAll();
}
return null;
}
}
}
|
51번 줄에서 DAO의 getAll() 메소드가 호출되었다.
getAll() 메소드에서 반환하는 DataModel 리스트는 LiveData 객체가 감싸고있다.
즉, LiveData의 메소드를 활용할 수 있게 되는 것이고 observe 메소드로 DataModel의 변화를 감지할 수 있게 되었다.
*변화가 감지되면 데이터를 갱신한다* 를 구현할 수 있게 되는 것이다.
'Android' 카테고리의 다른 글
Android Dagger-Hilt 적용기 (2) - Local Database (0) | 2020.11.06 |
---|---|
Android Dagger-Hilt 적용기 (1) - Dependency Injection (0) | 2020.11.06 |
안드로이드 Chip 레이아웃 - Chip + Chip Group (0) | 2020.03.24 |
Android RecyclerView + ItemTouchHelper - 드래그 앤 드롭, 스와이프 (0) | 2020.03.22 |
[Android] 디자인패턴 5 - MVVM패턴 (0) | 2020.03.22 |