Trying monarchy to manage realm

This commit is contained in:
ganfra 2018-10-18 11:16:02 +02:00
parent 1646687e6d
commit 3f07ed9806
9 changed files with 44 additions and 57 deletions

Binary file not shown.

View File

@ -22,6 +22,7 @@ allprojects {
google() google()
jcenter() jcenter()
maven { url 'https://dl.bintray.com/kotlin/kotlin-eap' } maven { url 'https://dl.bintray.com/kotlin/kotlin-eap' }
maven { url 'https://jitpack.io' }
} }
} }



View File

@ -68,6 +68,9 @@ dependencies {
implementation "com.squareup.moshi:moshi-adapters:$moshi_version" implementation "com.squareup.moshi:moshi-adapters:$moshi_version"
kapt "com.squareup.moshi:moshi-kotlin-codegen:$moshi_version" kapt "com.squareup.moshi:moshi-kotlin-codegen:$moshi_version"


// Database
implementation 'com.github.Zhuinden:realm-monarchy:0.5.1'

// Paging // Paging
implementation "android.arch.paging:runtime:1.0.1" implementation "android.arch.paging:runtime:1.0.1"



View File

@ -2,13 +2,13 @@ package im.vector.matrix.android.api


import android.arch.lifecycle.ProcessLifecycleOwner import android.arch.lifecycle.ProcessLifecycleOwner
import android.content.Context import android.content.Context
import com.zhuinden.monarchy.Monarchy
import im.vector.matrix.android.api.auth.Authenticator import im.vector.matrix.android.api.auth.Authenticator
import im.vector.matrix.android.api.session.Session import im.vector.matrix.android.api.session.Session
import im.vector.matrix.android.internal.auth.AuthModule import im.vector.matrix.android.internal.auth.AuthModule
import im.vector.matrix.android.internal.di.MatrixModule import im.vector.matrix.android.internal.di.MatrixModule
import im.vector.matrix.android.internal.di.NetworkModule import im.vector.matrix.android.internal.di.NetworkModule
import im.vector.matrix.android.internal.util.BackgroundDetectionObserver import im.vector.matrix.android.internal.util.BackgroundDetectionObserver
import io.realm.Realm
import org.koin.standalone.KoinComponent import org.koin.standalone.KoinComponent
import org.koin.standalone.StandAloneContext.loadKoinModules import org.koin.standalone.StandAloneContext.loadKoinModules
import org.koin.standalone.inject import org.koin.standalone.inject
@ -22,7 +22,7 @@ class Matrix(matrixOptions: MatrixOptions) : KoinComponent {
var currentSession: Session? = null var currentSession: Session? = null


init { init {
Realm.init(matrixOptions.context) Monarchy.init(matrixOptions.context)
val matrixModule = MatrixModule(matrixOptions) val matrixModule = MatrixModule(matrixOptions)
val networkModule = NetworkModule() val networkModule = NetworkModule()
val authModule = AuthModule() val authModule = AuthModule()

View File

@ -7,7 +7,6 @@ import im.vector.matrix.android.api.session.Session
import im.vector.matrix.android.api.session.room.Room import im.vector.matrix.android.api.session.room.Room
import im.vector.matrix.android.api.session.room.RoomService import im.vector.matrix.android.api.session.room.RoomService
import im.vector.matrix.android.internal.auth.data.SessionParams import im.vector.matrix.android.internal.auth.data.SessionParams
import im.vector.matrix.android.internal.database.SessionRealmHolder
import im.vector.matrix.android.internal.session.room.RoomSummaryObserver import im.vector.matrix.android.internal.session.room.RoomSummaryObserver
import im.vector.matrix.android.internal.session.sync.SyncModule import im.vector.matrix.android.internal.session.sync.SyncModule
import im.vector.matrix.android.internal.session.sync.job.SyncThread import im.vector.matrix.android.internal.session.sync.job.SyncThread
@ -18,8 +17,7 @@ import org.koin.standalone.getKoin
import org.koin.standalone.inject import org.koin.standalone.inject




class DefaultSession(private val sessionParams: SessionParams class DefaultSession(private val sessionParams: SessionParams) : Session, KoinComponent, RoomService {
) : Session, KoinComponent, RoomService {


companion object { companion object {
const val SCOPE: String = "session" const val SCOPE: String = "session"
@ -27,7 +25,6 @@ class DefaultSession(private val sessionParams: SessionParams


private lateinit var scope: Scope private lateinit var scope: Scope


private val realmInstanceHolder by inject<SessionRealmHolder>()
private val roomSummaryObserver by inject<RoomSummaryObserver>() private val roomSummaryObserver by inject<RoomSummaryObserver>()
private val roomService by inject<RoomService>() private val roomService by inject<RoomService>()
private val syncThread by inject<SyncThread>() private val syncThread by inject<SyncThread>()
@ -42,7 +39,6 @@ class DefaultSession(private val sessionParams: SessionParams
val syncModule = SyncModule() val syncModule = SyncModule()
StandAloneContext.loadKoinModules(listOf(sessionModule, syncModule)) StandAloneContext.loadKoinModules(listOf(sessionModule, syncModule))
scope = getKoin().getOrCreateScope(SCOPE) scope = getKoin().getOrCreateScope(SCOPE)
realmInstanceHolder.open()
roomSummaryObserver.start() roomSummaryObserver.start()
syncThread.start() syncThread.start()
} }
@ -54,7 +50,6 @@ class DefaultSession(private val sessionParams: SessionParams
assert(isOpen) assert(isOpen)
syncThread.kill() syncThread.kill()
roomSummaryObserver.dispose() roomSummaryObserver.dispose()
realmInstanceHolder.close()
scope.close() scope.close()
isOpen = false isOpen = false
} }

View File

@ -1,8 +1,8 @@
package im.vector.matrix.android.internal.session package im.vector.matrix.android.internal.session


import com.zhuinden.monarchy.Monarchy
import im.vector.matrix.android.api.session.room.RoomService import im.vector.matrix.android.api.session.room.RoomService
import im.vector.matrix.android.internal.auth.data.SessionParams import im.vector.matrix.android.internal.auth.data.SessionParams
import im.vector.matrix.android.internal.database.SessionRealmHolder
import im.vector.matrix.android.internal.legacy.MXDataHandler import im.vector.matrix.android.internal.legacy.MXDataHandler
import im.vector.matrix.android.internal.legacy.MXSession import im.vector.matrix.android.internal.legacy.MXSession
import im.vector.matrix.android.internal.legacy.data.store.MXFileStore import im.vector.matrix.android.internal.legacy.data.store.MXFileStore
@ -23,7 +23,7 @@ class SessionModule(private val sessionParams: SessionParams) : Module {
} }


scope(DefaultSession.SCOPE) { scope(DefaultSession.SCOPE) {
SessionRealmHolder(get()) Monarchy.Builder().setRealmConfiguration(get()).build()
} }


scope(DefaultSession.SCOPE) { scope(DefaultSession.SCOPE) {
@ -34,11 +34,11 @@ class SessionModule(private val sessionParams: SessionParams) : Module {
} }


scope(DefaultSession.SCOPE) { scope(DefaultSession.SCOPE) {
RoomSummaryObserver(get(), get(), get()) RoomSummaryObserver(get())
} }


scope(DefaultSession.SCOPE) { scope(DefaultSession.SCOPE) {
DefaultRoomService(get(), get()) as RoomService DefaultRoomService(get()) as RoomService
} }


scope(DefaultSession.SCOPE) { scope(DefaultSession.SCOPE) {

View File

@ -1,38 +1,36 @@
package im.vector.matrix.android.internal.session.room package im.vector.matrix.android.internal.session.room


import android.arch.lifecycle.LiveData import android.arch.lifecycle.LiveData
import com.zhuinden.monarchy.Monarchy
import im.vector.matrix.android.api.session.room.Room import im.vector.matrix.android.api.session.room.Room
import im.vector.matrix.android.api.session.room.RoomService import im.vector.matrix.android.api.session.room.RoomService
import im.vector.matrix.android.internal.database.RealmLiveData
import im.vector.matrix.android.internal.database.SessionRealmHolder
import im.vector.matrix.android.internal.database.model.RoomEntity import im.vector.matrix.android.internal.database.model.RoomEntity
import im.vector.matrix.android.internal.database.query.getAll import im.vector.matrix.android.internal.database.query.getAll
import im.vector.matrix.android.internal.database.query.getForId import im.vector.matrix.android.internal.database.query.getForId
import io.realm.Realm
import io.realm.RealmConfiguration


class DefaultRoomService(private val realmConfiguration: RealmConfiguration, class DefaultRoomService(private val monarchy: Monarchy) : RoomService {
val mainThreadRealm: SessionRealmHolder)
: RoomService {


override fun getAllRooms(): List<Room> { override fun getAllRooms(): List<Room> {
val realm = Realm.getInstance(realmConfiguration) var rooms: List<Room> = emptyList()
val rooms = RoomEntity.getAll(realm).findAll().map { DefaultRoom(it.roomId) } monarchy.doWithRealm { realm ->
realm.close() rooms = RoomEntity.getAll(realm).findAll().map { DefaultRoom(it.roomId) }
}
return rooms return rooms
} }


override fun getRoom(roomId: String): Room? { override fun getRoom(roomId: String): Room? {
val realm = Realm.getInstance(realmConfiguration) var room: Room? = null
val room = RoomEntity.getForId(realm, roomId)?.let { DefaultRoom(it.roomId) } monarchy.doWithRealm { realm ->
realm.close() room = RoomEntity.getForId(realm, roomId)?.let { DefaultRoom(it.roomId) }
}
return room return room
} }


override fun rooms(): LiveData<List<Room>> { override fun rooms(): LiveData<List<Room>> {
val roomResults = RoomEntity.getAll(mainThreadRealm.instance).findAllAsync() return monarchy.findAllMappedWithChanges(
return RealmLiveData(roomResults) { DefaultRoom(it.roomId) } { realm -> RoomEntity.getAll(realm) },
{ DefaultRoom(it.roomId) }
)
} }



} }

View File

@ -1,9 +1,9 @@
package im.vector.matrix.android.internal.session.room package im.vector.matrix.android.internal.session.room


import com.zhuinden.monarchy.Monarchy
import im.vector.matrix.android.api.session.events.model.EventType import im.vector.matrix.android.api.session.events.model.EventType
import im.vector.matrix.android.api.session.room.model.RoomNameContent import im.vector.matrix.android.api.session.room.model.RoomNameContent
import im.vector.matrix.android.api.session.room.model.RoomTopicContent import im.vector.matrix.android.api.session.room.model.RoomTopicContent
import im.vector.matrix.android.internal.database.SessionRealmHolder
import im.vector.matrix.android.internal.database.mapper.asDomain import im.vector.matrix.android.internal.database.mapper.asDomain
import im.vector.matrix.android.internal.database.model.EventEntity import im.vector.matrix.android.internal.database.model.EventEntity
import im.vector.matrix.android.internal.database.model.RoomEntity import im.vector.matrix.android.internal.database.model.RoomEntity
@ -11,28 +11,22 @@ import im.vector.matrix.android.internal.database.model.RoomSummaryEntity
import im.vector.matrix.android.internal.database.query.getAll import im.vector.matrix.android.internal.database.query.getAll
import im.vector.matrix.android.internal.database.query.getAllFromRoom import im.vector.matrix.android.internal.database.query.getAllFromRoom
import im.vector.matrix.android.internal.database.query.getLast import im.vector.matrix.android.internal.database.query.getLast
import im.vector.matrix.android.internal.util.MatrixCoroutineDispatchers
import io.realm.Realm
import io.realm.RealmConfiguration
import io.realm.RealmResults import io.realm.RealmResults
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import java.util.concurrent.atomic.AtomicBoolean import java.util.concurrent.atomic.AtomicBoolean


internal class RoomSummaryObserver(private val mainThreadRealm: SessionRealmHolder, internal class RoomSummaryObserver(private val monarchy: Monarchy) {
private val matrixCoroutineDispatchers: MatrixCoroutineDispatchers,
private val realmConfiguration: RealmConfiguration
) {


private lateinit var roomResults: RealmResults<RoomEntity> private lateinit var roomResults: RealmResults<RoomEntity>
private var isStarted = AtomicBoolean(false) private var isStarted = AtomicBoolean(false)


fun start() { fun start() {
if (isStarted.compareAndSet(false, true)) { if (isStarted.compareAndSet(false, true)) {
roomResults = RoomEntity.getAll(mainThreadRealm.instance).findAllAsync() monarchy.doWithRealm {
roomResults.addChangeListener { rooms, changeSet -> roomResults = RoomEntity.getAll(it).findAllAsync()
manageRoomResults(rooms, changeSet.changes) roomResults.addChangeListener { rooms, changeSet ->
manageRoomResults(rooms, changeSet.insertions) manageRoomResults(rooms, changeSet.changes)
manageRoomResults(rooms, changeSet.insertions)
}
} }
} }
} }
@ -54,20 +48,18 @@ internal class RoomSummaryObserver(private val mainThreadRealm: SessionRealmHold
} }
} }


private fun manageRoom(roomId: String) = GlobalScope.launch(matrixCoroutineDispatchers.io) { private fun manageRoom(roomId: String) {
val realm = Realm.getInstance(realmConfiguration) monarchy.writeAsync { realm ->
val roomEvents = EventEntity.getAllFromRoom(realm, roomId) val roomEvents = EventEntity.getAllFromRoom(realm, roomId)
val lastNameEvent = roomEvents.getLast(EventType.STATE_ROOM_NAME)?.asDomain() val lastNameEvent = roomEvents.getLast(EventType.STATE_ROOM_NAME)?.asDomain()
val lastTopicEvent = roomEvents.getLast(EventType.STATE_ROOM_TOPIC)?.asDomain() val lastTopicEvent = roomEvents.getLast(EventType.STATE_ROOM_TOPIC)?.asDomain()
val lastMessageEvent = roomEvents.getLast(EventType.MESSAGE) val lastMessageEvent = roomEvents.getLast(EventType.MESSAGE)


realm.executeTransaction { realmInstance -> val roomSummary = realm.copyToRealmOrUpdate(RoomSummaryEntity(roomId))
val roomSummary = realmInstance.copyToRealmOrUpdate(RoomSummaryEntity(roomId))
roomSummary.displayName = lastNameEvent?.content<RoomNameContent>()?.name roomSummary.displayName = lastNameEvent?.content<RoomNameContent>()?.name
roomSummary.topic = lastTopicEvent?.content<RoomTopicContent>()?.topic roomSummary.topic = lastTopicEvent?.content<RoomTopicContent>()?.topic
roomSummary.lastMessage = lastMessageEvent roomSummary.lastMessage = lastMessageEvent
} }
realm.close()
} }


} }

View File

@ -1,5 +1,6 @@
package im.vector.matrix.android.internal.session.sync package im.vector.matrix.android.internal.session.sync


import com.zhuinden.monarchy.Monarchy
import im.vector.matrix.android.api.session.events.model.Event import im.vector.matrix.android.api.session.events.model.Event
import im.vector.matrix.android.internal.database.mapper.asEntity import im.vector.matrix.android.internal.database.mapper.asEntity
import im.vector.matrix.android.internal.database.model.ChunkEntity import im.vector.matrix.android.internal.database.model.ChunkEntity
@ -10,10 +11,9 @@ import im.vector.matrix.android.internal.database.query.getLastChunkFromRoom
import im.vector.matrix.android.internal.session.sync.model.InvitedRoomSync import im.vector.matrix.android.internal.session.sync.model.InvitedRoomSync
import im.vector.matrix.android.internal.session.sync.model.RoomSync import im.vector.matrix.android.internal.session.sync.model.RoomSync
import io.realm.Realm import io.realm.Realm
import io.realm.RealmConfiguration




class RoomSyncHandler(private val realmConfiguration: RealmConfiguration) { class RoomSyncHandler(private val monarchy: Monarchy) {


sealed class HandlingStrategy { sealed class HandlingStrategy {
data class JOINED(val data: Map<String, RoomSync>) : HandlingStrategy() data class JOINED(val data: Map<String, RoomSync>) : HandlingStrategy()
@ -22,16 +22,14 @@ class RoomSyncHandler(private val realmConfiguration: RealmConfiguration) {
} }


fun handleRoomSync(handlingStrategy: HandlingStrategy) { fun handleRoomSync(handlingStrategy: HandlingStrategy) {
val realm = Realm.getInstance(realmConfiguration) monarchy.writeAsync { realm ->
realm.executeTransaction { realmInstance ->
val roomEntities = when (handlingStrategy) { val roomEntities = when (handlingStrategy) {
is HandlingStrategy.JOINED -> handlingStrategy.data.map { handleJoinedRoom(realm, it.key, it.value) } is HandlingStrategy.JOINED -> handlingStrategy.data.map { handleJoinedRoom(realm, it.key, it.value) }
is HandlingStrategy.INVITED -> handlingStrategy.data.map { handleInvitedRoom(realm, it.key, it.value) } is HandlingStrategy.INVITED -> handlingStrategy.data.map { handleInvitedRoom(realm, it.key, it.value) }
is HandlingStrategy.LEFT -> handlingStrategy.data.map { handleLeftRoom(it.key, it.value) } is HandlingStrategy.LEFT -> handlingStrategy.data.map { handleLeftRoom(it.key, it.value) }
} }
realmInstance.insertOrUpdate(roomEntities) realm.insertOrUpdate(roomEntities)
} }
realm.close()
} }