diff --git a/.idea/caches/build_file_checksums.ser b/.idea/caches/build_file_checksums.ser index acb3a3d5..4569da29 100644 Binary files a/.idea/caches/build_file_checksums.ser and b/.idea/caches/build_file_checksums.ser differ diff --git a/build.gradle b/build.gradle index 64874028..1eb48893 100644 --- a/build.gradle +++ b/build.gradle @@ -22,6 +22,7 @@ allprojects { google() jcenter() maven { url 'https://dl.bintray.com/kotlin/kotlin-eap' } + maven { url 'https://jitpack.io' } } } diff --git a/matrix-sdk-android/build.gradle b/matrix-sdk-android/build.gradle index 8fb1dadd..b705b3c9 100644 --- a/matrix-sdk-android/build.gradle +++ b/matrix-sdk-android/build.gradle @@ -68,6 +68,9 @@ dependencies { implementation "com.squareup.moshi:moshi-adapters:$moshi_version" kapt "com.squareup.moshi:moshi-kotlin-codegen:$moshi_version" + // Database + implementation 'com.github.Zhuinden:realm-monarchy:0.5.1' + // Paging implementation "android.arch.paging:runtime:1.0.1" diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/Matrix.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/Matrix.kt index 6ff5a5ba..ac4c74a2 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/Matrix.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/Matrix.kt @@ -2,13 +2,13 @@ package im.vector.matrix.android.api import android.arch.lifecycle.ProcessLifecycleOwner import android.content.Context +import com.zhuinden.monarchy.Monarchy import im.vector.matrix.android.api.auth.Authenticator import im.vector.matrix.android.api.session.Session import im.vector.matrix.android.internal.auth.AuthModule import im.vector.matrix.android.internal.di.MatrixModule import im.vector.matrix.android.internal.di.NetworkModule import im.vector.matrix.android.internal.util.BackgroundDetectionObserver -import io.realm.Realm import org.koin.standalone.KoinComponent import org.koin.standalone.StandAloneContext.loadKoinModules import org.koin.standalone.inject @@ -22,7 +22,7 @@ class Matrix(matrixOptions: MatrixOptions) : KoinComponent { var currentSession: Session? = null init { - Realm.init(matrixOptions.context) + Monarchy.init(matrixOptions.context) val matrixModule = MatrixModule(matrixOptions) val networkModule = NetworkModule() val authModule = AuthModule() diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/DefaultSession.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/DefaultSession.kt index 43cee60d..95bfe7fc 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/DefaultSession.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/DefaultSession.kt @@ -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.RoomService 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.sync.SyncModule import im.vector.matrix.android.internal.session.sync.job.SyncThread @@ -18,8 +17,7 @@ import org.koin.standalone.getKoin import org.koin.standalone.inject -class DefaultSession(private val sessionParams: SessionParams -) : Session, KoinComponent, RoomService { +class DefaultSession(private val sessionParams: SessionParams) : Session, KoinComponent, RoomService { companion object { const val SCOPE: String = "session" @@ -27,7 +25,6 @@ class DefaultSession(private val sessionParams: SessionParams private lateinit var scope: Scope - private val realmInstanceHolder by inject() private val roomSummaryObserver by inject() private val roomService by inject() private val syncThread by inject() @@ -42,7 +39,6 @@ class DefaultSession(private val sessionParams: SessionParams val syncModule = SyncModule() StandAloneContext.loadKoinModules(listOf(sessionModule, syncModule)) scope = getKoin().getOrCreateScope(SCOPE) - realmInstanceHolder.open() roomSummaryObserver.start() syncThread.start() } @@ -54,7 +50,6 @@ class DefaultSession(private val sessionParams: SessionParams assert(isOpen) syncThread.kill() roomSummaryObserver.dispose() - realmInstanceHolder.close() scope.close() isOpen = false } diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/SessionModule.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/SessionModule.kt index 03af4f0e..4e5b1d92 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/SessionModule.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/SessionModule.kt @@ -1,8 +1,8 @@ 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.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.MXSession import im.vector.matrix.android.internal.legacy.data.store.MXFileStore @@ -23,7 +23,7 @@ class SessionModule(private val sessionParams: SessionParams) : Module { } scope(DefaultSession.SCOPE) { - SessionRealmHolder(get()) + Monarchy.Builder().setRealmConfiguration(get()).build() } scope(DefaultSession.SCOPE) { @@ -34,11 +34,11 @@ class SessionModule(private val sessionParams: SessionParams) : Module { } scope(DefaultSession.SCOPE) { - RoomSummaryObserver(get(), get(), get()) + RoomSummaryObserver(get()) } scope(DefaultSession.SCOPE) { - DefaultRoomService(get(), get()) as RoomService + DefaultRoomService(get()) as RoomService } scope(DefaultSession.SCOPE) { diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/DefaultRoomService.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/DefaultRoomService.kt index 3fe38f76..1177a95d 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/DefaultRoomService.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/DefaultRoomService.kt @@ -1,38 +1,36 @@ package im.vector.matrix.android.internal.session.room 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.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.query.getAll import im.vector.matrix.android.internal.database.query.getForId -import io.realm.Realm -import io.realm.RealmConfiguration -class DefaultRoomService(private val realmConfiguration: RealmConfiguration, - val mainThreadRealm: SessionRealmHolder) - : RoomService { +class DefaultRoomService(private val monarchy: Monarchy) : RoomService { override fun getAllRooms(): List { - val realm = Realm.getInstance(realmConfiguration) - val rooms = RoomEntity.getAll(realm).findAll().map { DefaultRoom(it.roomId) } - realm.close() + var rooms: List = emptyList() + monarchy.doWithRealm { realm -> + rooms = RoomEntity.getAll(realm).findAll().map { DefaultRoom(it.roomId) } + } return rooms } override fun getRoom(roomId: String): Room? { - val realm = Realm.getInstance(realmConfiguration) - val room = RoomEntity.getForId(realm, roomId)?.let { DefaultRoom(it.roomId) } - realm.close() + var room: Room? = null + monarchy.doWithRealm { realm -> + room = RoomEntity.getForId(realm, roomId)?.let { DefaultRoom(it.roomId) } + } return room } override fun rooms(): LiveData> { - val roomResults = RoomEntity.getAll(mainThreadRealm.instance).findAllAsync() - return RealmLiveData(roomResults) { DefaultRoom(it.roomId) } + return monarchy.findAllMappedWithChanges( + { realm -> RoomEntity.getAll(realm) }, + { DefaultRoom(it.roomId) } + ) } - } \ No newline at end of file diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/RoomSummaryObserver.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/RoomSummaryObserver.kt index 3bd9a87b..f35b06fd 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/RoomSummaryObserver.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/RoomSummaryObserver.kt @@ -1,9 +1,9 @@ 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.room.model.RoomNameContent 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.model.EventEntity 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.getAllFromRoom 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 kotlinx.coroutines.GlobalScope -import kotlinx.coroutines.launch import java.util.concurrent.atomic.AtomicBoolean -internal class RoomSummaryObserver(private val mainThreadRealm: SessionRealmHolder, - private val matrixCoroutineDispatchers: MatrixCoroutineDispatchers, - private val realmConfiguration: RealmConfiguration -) { +internal class RoomSummaryObserver(private val monarchy: Monarchy) { private lateinit var roomResults: RealmResults private var isStarted = AtomicBoolean(false) fun start() { if (isStarted.compareAndSet(false, true)) { - roomResults = RoomEntity.getAll(mainThreadRealm.instance).findAllAsync() - roomResults.addChangeListener { rooms, changeSet -> - manageRoomResults(rooms, changeSet.changes) - manageRoomResults(rooms, changeSet.insertions) + monarchy.doWithRealm { + roomResults = RoomEntity.getAll(it).findAllAsync() + roomResults.addChangeListener { rooms, changeSet -> + 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) { - val realm = Realm.getInstance(realmConfiguration) - val roomEvents = EventEntity.getAllFromRoom(realm, roomId) - val lastNameEvent = roomEvents.getLast(EventType.STATE_ROOM_NAME)?.asDomain() - val lastTopicEvent = roomEvents.getLast(EventType.STATE_ROOM_TOPIC)?.asDomain() - val lastMessageEvent = roomEvents.getLast(EventType.MESSAGE) + private fun manageRoom(roomId: String) { + monarchy.writeAsync { realm -> + val roomEvents = EventEntity.getAllFromRoom(realm, roomId) + val lastNameEvent = roomEvents.getLast(EventType.STATE_ROOM_NAME)?.asDomain() + val lastTopicEvent = roomEvents.getLast(EventType.STATE_ROOM_TOPIC)?.asDomain() + val lastMessageEvent = roomEvents.getLast(EventType.MESSAGE) - realm.executeTransaction { realmInstance -> - val roomSummary = realmInstance.copyToRealmOrUpdate(RoomSummaryEntity(roomId)) + val roomSummary = realm.copyToRealmOrUpdate(RoomSummaryEntity(roomId)) roomSummary.displayName = lastNameEvent?.content()?.name roomSummary.topic = lastTopicEvent?.content()?.topic roomSummary.lastMessage = lastMessageEvent } - realm.close() } } \ No newline at end of file diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/RoomSyncHandler.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/RoomSyncHandler.kt index 6be5dea3..54292b13 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/RoomSyncHandler.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/RoomSyncHandler.kt @@ -1,5 +1,6 @@ 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.internal.database.mapper.asEntity 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.RoomSync import io.realm.Realm -import io.realm.RealmConfiguration -class RoomSyncHandler(private val realmConfiguration: RealmConfiguration) { +class RoomSyncHandler(private val monarchy: Monarchy) { sealed class HandlingStrategy { data class JOINED(val data: Map) : HandlingStrategy() @@ -22,16 +22,14 @@ class RoomSyncHandler(private val realmConfiguration: RealmConfiguration) { } fun handleRoomSync(handlingStrategy: HandlingStrategy) { - val realm = Realm.getInstance(realmConfiguration) - realm.executeTransaction { realmInstance -> + monarchy.writeAsync { realm -> val roomEntities = when (handlingStrategy) { 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.LEFT -> handlingStrategy.data.map { handleLeftRoom(it.key, it.value) } } - realmInstance.insertOrUpdate(roomEntities) + realm.insertOrUpdate(roomEntities) } - realm.close() }