일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- JNI
- mqtt
- ozd
- Flavors
- TIZEN
- socket.io
- socket-server
- git-push
- cloud-firestore
- OZViewer
- mosquitto
- Firebase
- AWS
- Galaxy Watch
- ActivityResult-API
- google-login
- Java8
- 워치
- BottomSheetDialog
- 오즈뷰어
- Android
- socket-client
- hung-up
- Dva
- Kotlin
- NoSuchMethodError
- firebase-database
- git
- gradle
- firebase-storage
- Today
- Total
Hyeyeon blog
[Android] Kotlin - Realm 본문
Realm DB : 내장 데이터베이스 라이브러리 [Reference]
(1) 데이터 모델
- '데이터 컨테이너' 모델을 사용하여 Realm에 객체로 저장 (ORM이 아님)
(2) Realm
- Realm의 데이터베이스 컨테이너의 인스턴스
- Realm은 단일 애플리케이션 차원의 DB가 아님
: 하나의 애플리케이션에서 여러 Realm을 사용하여 데이터를 구성/저장
- Realm은 테이블이 아님
: 전형적으로 테이블은 한 종류의 데이터만 저장하지만, Realm은 여러 종류의 객체를 저장할 수 있음
(3) 특징
- lazy loading
- Realm Object에 대한 호출 Thread를 유지해야 함
- 라이브러리 크기가 큼
1. .gradle 추가
// build.gradle (Module:app) apply plugin: 'realm-android' realm { syncEnabled = true kotlinExtensionsEnabled = true } // build.gradle (Project: .. ) buildscript { dependencies { classpath "io.realm:realm-gradle-plugin:5.8.0" } }
2. 사용할 객체에 RealmObject 상속
- open class로 선언해야함 (cannot inherit from final .. 발생)
open class Dog : RealmObject() { var name: String = "" var age: Int = 0 } open class Person : RealmObject() { @PrimaryKey var id : Int = 0 var name: String = "" var dogs: RealmList= RealmList() // Declare one-to-many relationships }
3. Realm 초기화
// Use them like regular java objects var dog = Dog() dog.name = "Rex" dog.age = 1 // Initialize Realm (just once per application) Realm.init(context) // Get a Realm instance for this thread var realm = Realm.getDefaultInstance()
4. Object 저장
- copyToRealm(): 새로운 Realm 객체를 생성 (이미 같은 값의 기본키를 갖는 객체가 있으면 Exception 발생);
unmanaged 객체, 즉 POJO 인스턴스를 복사해서 managed 인스턴스를 생성(자동으로 Proxy객체도 생성해서 넘겨줌)
- copyToRealmOrUpdate(): 같은 값의 기본키를 가진 객체가 있으면 업데이트를, 없으면 객체를 생성
- createObject(): 새로운 managed 인스턴스를 생성
4-1. commitTransaction()
// Persist your data in a transaction realm.beginTransaction() // Persist unmanaged objects val managedDog = realm.copyToRealm(dog) // Create managed objects directly var person = realm.createObject(Person::class.java)
person.dogs.add(managedDog) realm.commitTransaction()
4-2. executeTransaction()
- 자동으로 begin/commit/cancel을 처리해줌
realm.executeTransaction {
bgRealm -> val managedDog = bgRealm.copyToRealm(dog)
var person = bgRealm.createObject(Person::class.java) person.dogs.add(managedDog)
bgRealm.copyToRealm(person) }
4-3. executeTransactionAsync()
- 비동기 트랜잭션으로, background thread에서 realm이 트랜잭션을 처리함
- UI thread의 blocking을 피하고 싶을 때 사용할 수 있음
realm.executeTransactionAsync({ // Execute bgRealm -> var managedDog = realm.copyToRealm(dog) var person = bgRealm.createObject(Person::class.java) person.dogs.add(managedDog)
bgRealm.copyToRealm(person) }, { // onSuccess realm.close() }, { // onError throwable -> realm.close(( }) }
5. Object 조회 [Reference]
- lessThan/ lessThenOrEqualTo/ greaterThan/ graterThenOrEqualTo
- equalTo/ notEqualTo
ex) equalTo("name", "Jill") // (필드 명, 비교 값)
- in: 해당 필드의 값이 리스트의 값과 일치
ex) in("name", new String[]{"Jill", "William", "Trillian"})
- isEmpty/ isNotEmpty
- isNull/ isNotNull
val puppies: RealmResults<Dog> = realm.where(Dog::class.java).lessThan("age", 2).findAll()
6. Object 업데이트
- 변경을 원하는 필드에 값을 set
realm.where(Dog::class.java).equalTo("age", 2).findFirst().name = "John"
7. Realm close [Reference]
- 네이티브 메모리 해제와 파일 서술자를 다루기 위해 Closable 구현
- 하나의 스레드에서 getInstance()가 호출된 횟수만큼 close()가 호출되어야 함
- UI 스레드가 대상일 경우, onDestory()에서 close() 호출
realm.close()
8. 기타
- autoIncrement를 지원하지 않아서 직접 구현해줘야 함 [참고]
- primaryKey를 갖고있는 객체는 createObject()로 구현
- Can't commit a non-existing write transaction in.. : beginTransaction() 없이 commitTransaction() 호출 시 발생
- @Ignore : 해당 필드를 제외시키고 싶을 경우 사용
- Kakao Map과 함께 사용 할 경우 추가 [참고]
android {
//...
packagingOptions {
exclude "lib/arm64-v8a/librealm-jni.so"
}
//...
}
- Failed resolution of: Lcom/google/android/gms/common/R$string; .. 발생 시, realm을 최신 버전으로 변경 [릴리즈 버전 참고]
- Object의 getter/setter 지원하지 않음 (select 시, 객체의 setter 호출X)- primaryKey를 갖고있는 객체는 createObject()로 구현
- 디버깅 시 proxy 값은 보이지만 실제 객체에는 값이 안보이는 경우 => Realm.copyToRealm 사용
val puppies: RealmResults<Dog> = realm.where(Dog::class.java).lessThan("age", 2).findAll() // ...findAll().toList() 호출하는 경우, 값이 없음 val list = realm.copyFromRealm(puppies)
[참고 및 출처]
[Realm 의 마법을 이루는 원리, Realm Java의 바이트 코드 조작]
'개발 > Android' 카테고리의 다른 글
[Android] Dependency Injection vs Service Locator (0) | 2019.01.22 |
---|---|
[Android] Floating Button size (0) | 2019.01.17 |
[Android] TextInputLayout (0) | 2019.01.17 |
[Android] Kotlin - Firebase Dynamic Link (0) | 2019.01.10 |
[Android] Kotlin - Coroutine with Retrofit2 (0) | 2018.12.31 |