오늘은 ListView와 Room을 사용해 데이터베이스에 대해 다뤄보겠습니다!
Room 이란?
- Room은 ORM(Object Relational Mapping) 라이브러리입니다. Room은 데이터베이스의 객체를 자바나 코틀린 객체로 매핑해주는것 입니다. Room은 SQLite의 추상레이어 위에 제공하고 있으며 SQLite의 모든 기능을 제공하면서 데이터베이스 접근을 편하게 해줍니다.
Room과 SQLite 차이점?
- SQLite 경우 쿼리에 대한 에러를 컴파일에 확인하는것이 없지만 Room에서는 컴파일 도중 SQL에 대한 유효성을 검사 가능합니다
- 스키마가 변경이 될경우 SQL쿼리를 수동으로 업데이트 해야하지만 Room의 경우는 쉽게 해결이 가능합니다.
- SQLite 경우 Java데이터 객체를 변경하기위해 많은 상용구 코드를 사용해야하지만 ROOM의 경우 ORM라이브러리가 t상용구 코드없이 매핑 가능합니다.
Room 구성요소
- Database : 데이터베이스 보유자입니다.
- Entity : Database 내의 테이블을 뜻합니다.
- Dao : 데이터베이스에 엑세스하는데 사용되는 메소드들을 갖고있습니다. select, insert, delete, join...등 데이터를 관한 처리를 할 수 있습니다.
1. Room Gradle 설정
Room을 사용하기 위해 build.gradle의 dependencies에 다음 문장들을 추가해줍니다.
def room_version = "2.2.5"
implementation "androidx.room:room-runtime:$room_version"
annotationProcessor "androidx.room:room-compiler:$room_version"
2. Entity를 만들어 줍니다 - Song.java
@Entity
public class Song {
@PrimaryKey(autoGenerate = true) //값 자동으로 생성
public int id;
@ColumnInfo(name = "title")
public String title;
@ColumnInfo(name = "singer")
public String singer;
}
3. Dao를 만들어줍니다 - SongDao.java
@Dao
public interface SongDao {
@Query("SELECT * FROM song") //전체 조회
List<Song> getAll();
@Query("SELECT title FROM song") //title만 조회
List<String> getTitleAll();
@Query("SELECT singer FROM song") //singer만 조회
List<String> getSingerAll();
@Insert
void insertAll(Song... songs);
@Delete
void delete(Song song);
}
4. Database를 만들어줍니다 - SongDatabase.java
@Database(entities = {Song.class}, version = 1)
public abstract class SongDatabase extends RoomDatabase {
private static SongDatabase INSTANCE; //객체는 하나만 생성
public abstract SongDao songDao();
public static SongDatabase getAppDatabase(Context context){
if(INSTANCE == null){
INSTANCE = Room.databaseBuilder(context, SongDatabase.class , "song-db").allowMainThreadQueries().build();
}
return INSTANCE;
}
}
allowMainThreadQueries() - Room을 사용할 때 쿼리 호출은 메인스레드에서 처리하면 안되기 때문에 원래는 비동기처리를 위해 다른 조치를 취해줘야 합니다. 여기서는 테스트용이기 때문에 메인스레드에서 쿼리 호출을 임시로 허용했습니다.
5. 뷰를 만들어줍니다 - activity_main.xml
<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=".MainActivity">
<EditText
android:id="@+id/et_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="20dp"
android:layout_marginTop="20dp"
android:ems="10"
android:hint="노래 제목"
android:inputType="textPersonName"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<EditText
android:id="@+id/et_singer"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="20dp"
android:layout_marginTop="20dp"
android:ems="10"
android:hint="가수 이름"
android:inputType="textPersonName"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/et_title" />
<Button
android:id="@+id/btn_add"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="60dp"
android:layout_marginEnd="40dp"
android:text="확인"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ListView
android:id="@+id/lv_songs"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_marginTop="140dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
6. 데이터베이스에 저장된 값을 가져오고, 데이터를 추가할 수 있도록 해줍니다 - MainActivity.java
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
EditText et_title = (EditText)findViewById(R.id.et_title);
EditText et_signer = (EditText)findViewById(R.id.et_singer);
Button btn_add = (Button)findViewById(R.id.btn_add);
ListView lv_songs = (ListView)findViewById(R.id.lv_songs);
List<String> list = new ArrayList<>();
// 데이터베이스를 가져옴
SongDatabase songDatabase = SongDatabase.getAppDatabase(this);
//데이터베이스에 저장된 값을 가져옴
List<String> title_list = songDatabase.songDao().getTitleAll();
List<String> singer_list = songDatabase.songDao().getSingerAll();
String[] title_array = title_list.toArray(new String[title_list.size()]);
String[] singer_array = singer_list.toArray(new String[singer_list.size()]);
//가져온 값을 리스트뷰에 추가
for(int i=0; i<title_array.length; i++){
list.add(title_array[i] + " - " + singer_array[i]);
}
//어댑터 연결
ArrayAdapter<String> adapter = new ArrayAdapter<>(this,android.R.layout.simple_list_item_1,list);
lv_songs.setAdapter(adapter);
btn_add.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
String title = et_title.getText().toString();
String singer = et_signer.getText().toString();
if(title.equals(""))
Toast.makeText(getApplicationContext(),"제목을 입력하세요", Toast.LENGTH_SHORT);
if(singer.equals(""))
Toast.makeText(getApplicationContext(),"가수를 입력하세요", Toast.LENGTH_SHORT);
//데이터 추가
if(!title.equals("") && !singer.equals("")){
Song new_song = new Song();
new_song.title = title;
new_song.singer = singer;
songDatabase.songDao().insertAll(new_song);
adapter.notifyDataSetChanged();
}
}
});
}
}
실행화면
'Android' 카테고리의 다른 글
[Android] 네비게이션 드로어(Navigation Drawer) 사용하기 + 풀스크린(Fullscreen) (0) | 2020.12.27 |
---|---|
[Android] 카메라(Camera) 호출 후 이미지 크롭(Crop) 하기 (2) | 2020.12.26 |
[Android] 7주차 스터디 (Camera) (0) | 2020.11.29 |
[Android] 6주차 스터디 (Gallery) (0) | 2020.11.29 |
[Android] 5주차 스터디 (RecyclerView) (0) | 2020.11.25 |