일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- Kotlin
- 디자인패턴
- 코틀린
- 추상 팩토리
- 팩토리 메소드
- 빌터패턴
- PrototypePattern
- builderPattern
- Singleton
- compose
- r
- F
- 함수형프로그래밍
- Design Pattern
- factory method
- 추상팩토리패턴
- 싱글톤
- 디자인패턴 #
- Abstract Factory
- designPattern
- El
- material3
- 안드로이드 디자인시스템
- Functional Programming
- 프로토타입 패턴
- ㅓ
- ㅋㅁ
- 옵저버 패턴
- Observer Pattern
- android designsystem
- Today
- Total
오늘도 더 나은 코드를 작성하였습니까?
Realm kotlin React to Changes 본문
모든 최신 앱은 데이터 변경이 시작된 위치에 관계없이 데이터가 변경될 때 대응할 수 있어야 합니다.
사용자가 list에 새 item을 추가하면 UI를 업데이트하거나, 알림을 표시하거나 메시지를 기록할 수 있습니다.
누군가 해당 list 업데이트하면 시각적 상태를 변경하거나, 네트워크 요청을 시작하고 싶을 수 있습니다.
마지막으로 누군가가 list item 삭제하면 UI에서 제거하고 싶을 것입니다.
Realm의 notification 시스템을 사용하면 변경을 일으킨 write transaction과 상관없이 데이터 변경을 감시하고 이에 대응할 수 있다
* Kotlin SDK의 frozen 아키텍처는 notification을 훨씬 더 중요하게 만듭니다.
Kotlin SDK에는 자동으로 업데이트되는 Live 객체가 없기 때문에 notification을 사용하여 UI와 데이터 레이어를 동기화 상태로 유지합니다.
이벤트에 대한 변경 사항을 구독할 수 있습니다.
RealmObject
class Character(): RealmObject {
@PrimaryKey
var name: String = ""
var species: String = ""
var age: Int = 0
constructor(name: String, species: String, age: Int) : this() {
this.name = name
this.species = species
this.age = age
}
}
class Fellowship() : RealmObject {
@PrimaryKey
var name: String = ""
var members: RealmList<Character> = realmListOf()
constructor(name: String, members: RealmList<Character>) : this() {
this.name = name
this.members = members
}
}
Data
val config = RealmConfiguration.Builder(setOf(Fellowship::class, Character::class))
.name(realmName)
.build()
val realm = Realm.open(config)
val frodo = Character("Frodo", "Hobbit", 51)
val samwise = Character("Samwise", "Hobbit", 39)
val aragorn = Character("Aragorn", "Dúnedain", 87)
val legolas = Character("Legolas", "Elf", 2931)
val gimli = Character("Gimli", "Dwarf", 140)
val gollum = Character("Gollum", "Hobbit", 589)
val fellowshipOfTheRing = Fellowship(
"Fellowship of the Ring",
realmListOf(frodo, samwise, aragorn, legolas, gimli))
realm.writeBlocking{
this.copyToRealm(fellowshipOfTheRing)
this.copyToRealm(gollum) // not in fellowship
}
realm.close()
Register a Query Change Listener
Realm 내의 모든 query에 알림 핸들러를 등록할 수 있습니다.
asFlow()를 사용하여 쿼리에서 Kotlin Flow를 만듭니다. 그런 다음 collect() 메서드를 사용하여 해당 Flow의 이벤트를 처리합니다.
UpdatedResults 유형의 이벤트는 아래 속성을 사용하여 쿼리와 일치하는 개체에 대한 모든 변경 사항을 기록합니다.
Property
|
Type
|
Description
|
insertions
|
IntArray
|
이 버전에 추가된 새 컬렉션의 인덱스입니다.
|
insertionRanges
|
Array<ListChangeSet.Range>
|
이 버전에 추가된 새 컬렉션의 인덱스 범위입니다.
|
changes
|
IntArray
|
이 버전에서 수정된 새 컬렉션의 개체 인덱스입니다.
|
changeRanges
|
Array<ListChangeSet.Range>
|
이 버전에 수정된 새 컬렉션의 인덱스 범위입니다.
|
deletions
|
IntArray
|
이 컬렉션에서 제거된 컬렉션의 이전 버전에 있는 인덱스입니다.
|
deletionRanges
|
Array<ListChangeSet.Range>
|
이 컬렉션에서 제거된 컬렉션의 이전 버전에 있는 인덱스 범위
|
list
|
RealmResults<T as RealmObject>
|
변경 사항에 대해 모니터링되는 결과 수집 |
// Listen for changes on whole collection
val characters = realm.query(Character::class)
// flow.collect() is blocking -- run it in a background context
val job = CoroutineScope(Dispatchers.Default).launch {
// create a Flow from that collection, then add a listener to the Flow
val charactersFlow = characters.asFlow()
val subscription = charactersFlow.collect { changes: ResultsChange<Character> ->
when (changes) {
// UpdatedResults means this change represents an update/insert/delete operation
is UpdatedResults -> {
changes.insertions // indexes of inserted objects
changes.insertionRanges // ranges of inserted objects
changes.changes // indexes of modified objects
changes.changeRanges // ranges of modified objects
changes.deletions // indexes of deleted objects
changes.deletionRanges // ranges of deleted objects
changes.list // the full collection of objects
}
else -> {
// types other than UpdatedResults are not changes -- ignore them
}
}
}
}
// Listen for changes on RealmResults
val hobbits = realm.query(Character::class, "species == 'Hobbit'")
val hobbitJob = CoroutineScope(Dispatchers.Default).launch {
val hobbitsFlow = hobbits.asFlow()
val hobbitsSubscription = hobbitsFlow.collect { changes: ResultsChange<Character> ->
// ... all the same data as above
}
}
Register a RealmObject Change Listener
Realm 내의 특정 개체에 대한 notification handler 를 등록할 수 있습니다.
Realm은 객체의 속성이 변경될 때 핸들러에 알립니다.
단일 객체에 변경 리스너를 등록하려면 realm.query.first()를 사용하여 RealmSingleQuery를 가져옵니다.
asFlow()를 사용하여 해당 쿼리에서 flow 생성합니다.
Handler 다음 아래 유형을 사용하여 객체 변경 사항을 전달하는 SingleQueryChange 개체를 수신합니다
Subtype
|
Properties
|
Notes
|
UpdatedObject
|
changedFields, obj
|
필드 이름을 isFieldChanged()에 전달하여 해당 필드가 변경되었는지 확인합니다.
|
DeletedObject
|
obj
|
obj는 항상 객체의 최신 버전을 반영하므로 항상 이 하위 유형에서 null 값을 반환합니다. |
// query for the specific object you intend to listen to
val frodo = realm.query(Character::class, "name == 'Frodo'").first()
// flow.collect() is blocking -- run it in a background context
val job = CoroutineScope(Dispatchers.Default).launch {
val frodoFlow = frodo.asFlow()
frodoFlow.collect { changes: SingleQueryChange<Character> ->
when (changes) {
is UpdatedObject -> {
changes.changedFields // the changed properties
changes.obj // the object in its newest state
changes.isFieldChanged("name") // check if a specific field changed in value
}
is DeletedObject -> {
// if the object has been deleted
changes.obj // returns null for deleted objects -- always reflects newest state
}
}
}
}
Register a RealmList Change Listener
RealmObject 내의 RealmObject List에 알림 핸들러를 등록할 수 있습니다.
목록 항목이 변경되면 Realm이 핸들러에 알립니다.
Property
|
Type
|
Description
|
insertions
|
IntArray
|
이 버전에 추가된 새 컬렉션의 인덱스입니다.
|
insertionRanges
|
Array<ListChangeSet.Range>
|
이 버전에 추가된 새 컬렉션의 인덱스 범위입니다.
|
changes
|
IntArray
|
이 버전에서 수정된 새 컬렉션의 개체 인덱스입니다.
|
changeRanges
|
Array<ListChangeSet.Range>
|
이 버전에서 수정된 새 컬렉션의 인덱스 범위입니다.
|
deletions
|
IntArray
|
이 컬렉션에서 제거된 컬렉션의 이전 버전에 있는 인덱스입니다.
|
deletionRanges
|
Array<ListChangeSet.Range>
|
이 컬렉션에서 제거된 컬렉션의 이전 버전에 있는 인덱스 범위입니다.
|
list
|
RealmResults<T as RealmObject>
|
변경 사항에 대해 모니터링되는 결과 수집. |
// query for the specific object you intend to listen to
val fellowshipOfTheRing = realm.query(Fellowship::class, "name == 'Fellowship of the Ring'").first().find()!!
val members = fellowshipOfTheRing.members
// flow.collect() is blocking -- run it in a background context
val job = CoroutineScope(Dispatchers.Default).launch {
val membersFlow = members.asFlow()
membersFlow.collect { changes: ListChange<Character> ->
when (changes) {
is UpdatedList -> {
changes.insertions // indexes of inserted objects
changes.insertionRanges // ranges of inserted objects
changes.changes // indexes of modified objects
changes.changeRanges // ranges of modified objects
changes.deletions // indexes of deleted objects
changes.deletionRanges // ranges of deleted objects
changes.list // the full collection of objects
}
is DeletedList -> {
// if the list was deleted
}
}
}
}.
Unsubscribe a Change Listener
보고 있는 데이터의 업데이트에 대한 알림을 더 이상 수신하지 않으려면 변경 수신기에서 구독을 취소합니다.
구독 취소하려면 둘러싸는 코루틴 취소 .
// query for the specific object you intend to listen to
val fellowshipOfTheRing = realm.query(Fellowship::class, "name == 'Fellowship of the Ring'").first().find()!!
val members = fellowshipOfTheRing.members
// flow.collect() is blocking -- run it in a background context
val job = CoroutineScope(Dispatchers.Default).launch {
val membersFlow = members.asFlow()
membersFlow.collect { changes: ListChange<Character> ->
// change listener stuff in here
}
}
job.cancel() // cancel the coroutine containing the listener