forked from GitHub-Mirror/riotX-android
Realm: avoid using monarchy thread for custom work
This commit is contained in:
parent
eefd09d022
commit
93ce0cc5e9
@ -17,7 +17,10 @@
|
|||||||
package im.vector.matrix.android.internal.database
|
package im.vector.matrix.android.internal.database
|
||||||
|
|
||||||
import com.zhuinden.monarchy.Monarchy
|
import com.zhuinden.monarchy.Monarchy
|
||||||
|
import im.vector.matrix.android.internal.util.createBackgroundHandler
|
||||||
import io.realm.OrderedCollectionChangeSet
|
import io.realm.OrderedCollectionChangeSet
|
||||||
|
import io.realm.Realm
|
||||||
|
import io.realm.RealmConfiguration
|
||||||
import io.realm.RealmObject
|
import io.realm.RealmObject
|
||||||
import io.realm.RealmResults
|
import io.realm.RealmResults
|
||||||
import java.util.concurrent.atomic.AtomicBoolean
|
import java.util.concurrent.atomic.AtomicBoolean
|
||||||
@ -29,17 +32,24 @@ internal interface LiveEntityObserver {
|
|||||||
fun isStarted(): Boolean
|
fun isStarted(): Boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
internal abstract class RealmLiveEntityObserver<T : RealmObject>(protected val monarchy: Monarchy)
|
internal abstract class RealmLiveEntityObserver<T : RealmObject>(protected val realmConfiguration: RealmConfiguration)
|
||||||
: LiveEntityObserver {
|
: LiveEntityObserver {
|
||||||
|
|
||||||
|
private companion object {
|
||||||
|
val BACKGROUND_HANDLER = createBackgroundHandler("LIVE_ENTITY_BACKGROUND")
|
||||||
|
}
|
||||||
|
|
||||||
protected abstract val query: Monarchy.Query<T>
|
protected abstract val query: Monarchy.Query<T>
|
||||||
private val isStarted = AtomicBoolean(false)
|
private val isStarted = AtomicBoolean(false)
|
||||||
|
private val backgroundRealm = AtomicReference<Realm>()
|
||||||
private lateinit var results: AtomicReference<RealmResults<T>>
|
private lateinit var results: AtomicReference<RealmResults<T>>
|
||||||
|
|
||||||
override fun start() {
|
override fun start() {
|
||||||
if (isStarted.compareAndSet(false, true)) {
|
if (isStarted.compareAndSet(false, true)) {
|
||||||
monarchy.postToMonarchyThread {
|
BACKGROUND_HANDLER.post {
|
||||||
val queryResults = query.createQuery(it).findAll()
|
val realm = Realm.getInstance(realmConfiguration)
|
||||||
|
backgroundRealm.set(realm)
|
||||||
|
val queryResults = query.createQuery(realm).findAll()
|
||||||
queryResults.addChangeListener { t, changeSet ->
|
queryResults.addChangeListener { t, changeSet ->
|
||||||
onChanged(t, changeSet)
|
onChanged(t, changeSet)
|
||||||
}
|
}
|
||||||
@ -50,8 +60,11 @@ internal abstract class RealmLiveEntityObserver<T : RealmObject>(protected val m
|
|||||||
|
|
||||||
override fun dispose() {
|
override fun dispose() {
|
||||||
if (isStarted.compareAndSet(true, false)) {
|
if (isStarted.compareAndSet(true, false)) {
|
||||||
monarchy.postToMonarchyThread {
|
BACKGROUND_HANDLER.post {
|
||||||
results.getAndSet(null).removeAllChangeListeners()
|
results.getAndSet(null).removeAllChangeListeners()
|
||||||
|
backgroundRealm.getAndSet(null).also {
|
||||||
|
it.close()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -50,7 +50,6 @@ import javax.inject.Inject
|
|||||||
internal class DefaultSession @Inject constructor(override val sessionParams: SessionParams,
|
internal class DefaultSession @Inject constructor(override val sessionParams: SessionParams,
|
||||||
private val context: Context,
|
private val context: Context,
|
||||||
private val liveEntityObservers: Set<@JvmSuppressWildcards LiveEntityObserver>,
|
private val liveEntityObservers: Set<@JvmSuppressWildcards LiveEntityObserver>,
|
||||||
private val monarchy: Monarchy,
|
|
||||||
private val sessionListeners: SessionListeners,
|
private val sessionListeners: SessionListeners,
|
||||||
private val roomService: RoomService,
|
private val roomService: RoomService,
|
||||||
private val roomDirectoryService: RoomDirectoryService,
|
private val roomDirectoryService: RoomDirectoryService,
|
||||||
@ -85,9 +84,6 @@ internal class DefaultSession @Inject constructor(override val sessionParams: Se
|
|||||||
assertMainThread()
|
assertMainThread()
|
||||||
assert(!isOpen)
|
assert(!isOpen)
|
||||||
isOpen = true
|
isOpen = true
|
||||||
if (!monarchy.isMonarchyThreadOpen) {
|
|
||||||
monarchy.openManually()
|
|
||||||
}
|
|
||||||
liveEntityObservers.forEach { it.start() }
|
liveEntityObservers.forEach { it.start() }
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -123,9 +119,6 @@ internal class DefaultSession @Inject constructor(override val sessionParams: Se
|
|||||||
stopSync()
|
stopSync()
|
||||||
liveEntityObservers.forEach { it.dispose() }
|
liveEntityObservers.forEach { it.dispose() }
|
||||||
cryptoService.close()
|
cryptoService.close()
|
||||||
if (monarchy.isMonarchyThreadOpen) {
|
|
||||||
monarchy.closeManually()
|
|
||||||
}
|
|
||||||
isOpen = false
|
isOpen = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,14 +27,16 @@ import im.vector.matrix.android.api.auth.data.Credentials
|
|||||||
import im.vector.matrix.android.internal.database.RealmLiveEntityObserver
|
import im.vector.matrix.android.internal.database.RealmLiveEntityObserver
|
||||||
import im.vector.matrix.android.internal.database.model.GroupEntity
|
import im.vector.matrix.android.internal.database.model.GroupEntity
|
||||||
import im.vector.matrix.android.internal.database.query.where
|
import im.vector.matrix.android.internal.database.query.where
|
||||||
|
import im.vector.matrix.android.internal.di.SessionDatabase
|
||||||
import im.vector.matrix.android.internal.worker.WorkerParamsFactory
|
import im.vector.matrix.android.internal.worker.WorkerParamsFactory
|
||||||
|
import io.realm.RealmConfiguration
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
private const val GET_GROUP_DATA_WORKER = "GET_GROUP_DATA_WORKER"
|
private const val GET_GROUP_DATA_WORKER = "GET_GROUP_DATA_WORKER"
|
||||||
|
|
||||||
internal class GroupSummaryUpdater @Inject constructor(private val context: Context,
|
internal class GroupSummaryUpdater @Inject constructor(private val context: Context,
|
||||||
private val credentials: Credentials,
|
private val credentials: Credentials,
|
||||||
monarchy: Monarchy) : RealmLiveEntityObserver<GroupEntity>(monarchy) {
|
@SessionDatabase realmConfiguration: RealmConfiguration) : RealmLiveEntityObserver<GroupEntity>(realmConfiguration) {
|
||||||
|
|
||||||
override val query = Monarchy.Query<GroupEntity> { GroupEntity.where(it) }
|
override val query = Monarchy.Query<GroupEntity> { GroupEntity.where(it) }
|
||||||
|
|
||||||
|
@ -22,8 +22,10 @@ import im.vector.matrix.android.internal.database.RealmLiveEntityObserver
|
|||||||
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.query.types
|
import im.vector.matrix.android.internal.database.query.types
|
||||||
|
import im.vector.matrix.android.internal.di.SessionDatabase
|
||||||
import im.vector.matrix.android.internal.task.TaskExecutor
|
import im.vector.matrix.android.internal.task.TaskExecutor
|
||||||
import im.vector.matrix.android.internal.task.configureWith
|
import im.vector.matrix.android.internal.task.configureWith
|
||||||
|
import io.realm.RealmConfiguration
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
@ -33,11 +35,11 @@ import javax.inject.Inject
|
|||||||
* The summaries can then be extracted and added (as a decoration) to a TimelineEvent for final display.
|
* The summaries can then be extracted and added (as a decoration) to a TimelineEvent for final display.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
internal class EventRelationsAggregationUpdater @Inject constructor(monarchy: Monarchy,
|
internal class EventRelationsAggregationUpdater @Inject constructor(@SessionDatabase realmConfiguration: RealmConfiguration,
|
||||||
private val credentials: Credentials,
|
private val credentials: Credentials,
|
||||||
private val task: EventRelationsAggregationTask,
|
private val task: EventRelationsAggregationTask,
|
||||||
private val taskExecutor: TaskExecutor) :
|
private val taskExecutor: TaskExecutor) :
|
||||||
RealmLiveEntityObserver<EventEntity>(monarchy) {
|
RealmLiveEntityObserver<EventEntity>(realmConfiguration) {
|
||||||
|
|
||||||
override val query = Monarchy.Query<EventEntity> {
|
override val query = Monarchy.Query<EventEntity> {
|
||||||
EventEntity.types(it, listOf(
|
EventEntity.types(it, listOf(
|
||||||
|
@ -23,9 +23,11 @@ import im.vector.matrix.android.internal.database.RealmLiveEntityObserver
|
|||||||
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.query.where
|
import im.vector.matrix.android.internal.database.query.where
|
||||||
|
import im.vector.matrix.android.internal.di.SessionDatabase
|
||||||
import im.vector.matrix.android.internal.session.SessionScope
|
import im.vector.matrix.android.internal.session.SessionScope
|
||||||
import im.vector.matrix.android.internal.task.TaskExecutor
|
import im.vector.matrix.android.internal.task.TaskExecutor
|
||||||
import im.vector.matrix.android.internal.task.configureWith
|
import im.vector.matrix.android.internal.task.configureWith
|
||||||
|
import io.realm.RealmConfiguration
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
@ -33,11 +35,11 @@ import javax.inject.Inject
|
|||||||
* Listens to the database for the insertion of any redaction event.
|
* Listens to the database for the insertion of any redaction event.
|
||||||
* As it will actually delete the content, it should be called last in the list of listener.
|
* As it will actually delete the content, it should be called last in the list of listener.
|
||||||
*/
|
*/
|
||||||
internal class EventsPruner @Inject constructor(monarchy: Monarchy,
|
internal class EventsPruner @Inject constructor(@SessionDatabase realmConfiguration: RealmConfiguration,
|
||||||
private val credentials: Credentials,
|
private val credentials: Credentials,
|
||||||
private val pruneEventTask: PruneEventTask,
|
private val pruneEventTask: PruneEventTask,
|
||||||
private val taskExecutor: TaskExecutor) :
|
private val taskExecutor: TaskExecutor) :
|
||||||
RealmLiveEntityObserver<EventEntity>(monarchy) {
|
RealmLiveEntityObserver<EventEntity>(realmConfiguration) {
|
||||||
|
|
||||||
override val query = Monarchy.Query<EventEntity> { EventEntity.where(it, type = EventType.REDACTION) }
|
override val query = Monarchy.Query<EventEntity> { EventEntity.where(it, type = EventType.REDACTION) }
|
||||||
|
|
||||||
|
@ -16,9 +16,6 @@
|
|||||||
|
|
||||||
package im.vector.matrix.android.internal.session.room.timeline
|
package im.vector.matrix.android.internal.session.room.timeline
|
||||||
|
|
||||||
import android.os.Handler
|
|
||||||
import android.os.HandlerThread
|
|
||||||
import android.os.Looper
|
|
||||||
import im.vector.matrix.android.api.MatrixCallback
|
import im.vector.matrix.android.api.MatrixCallback
|
||||||
import im.vector.matrix.android.api.session.crypto.CryptoService
|
import im.vector.matrix.android.api.session.crypto.CryptoService
|
||||||
import im.vector.matrix.android.api.session.events.model.EventType
|
import im.vector.matrix.android.api.session.events.model.EventType
|
||||||
@ -43,6 +40,8 @@ import im.vector.matrix.android.internal.database.query.whereInRoom
|
|||||||
import im.vector.matrix.android.internal.task.TaskExecutor
|
import im.vector.matrix.android.internal.task.TaskExecutor
|
||||||
import im.vector.matrix.android.internal.task.configureWith
|
import im.vector.matrix.android.internal.task.configureWith
|
||||||
import im.vector.matrix.android.internal.util.Debouncer
|
import im.vector.matrix.android.internal.util.Debouncer
|
||||||
|
import im.vector.matrix.android.internal.util.createBackgroundHandler
|
||||||
|
import im.vector.matrix.android.internal.util.createUIHandler
|
||||||
import io.realm.OrderedCollectionChangeSet
|
import io.realm.OrderedCollectionChangeSet
|
||||||
import io.realm.OrderedRealmCollectionChangeListener
|
import io.realm.OrderedRealmCollectionChangeListener
|
||||||
import io.realm.Realm
|
import io.realm.Realm
|
||||||
@ -75,9 +74,7 @@ internal class DefaultTimeline(
|
|||||||
) : Timeline {
|
) : Timeline {
|
||||||
|
|
||||||
private companion object {
|
private companion object {
|
||||||
val BACKGROUND_HANDLER = Handler(
|
val BACKGROUND_HANDLER = createBackgroundHandler("TIMELINE_DB_THREAD")
|
||||||
HandlerThread("TIMELINE_DB_THREAD").apply { start() }.looper
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override var listener: Timeline.Listener? = null
|
override var listener: Timeline.Listener? = null
|
||||||
@ -90,7 +87,7 @@ internal class DefaultTimeline(
|
|||||||
|
|
||||||
private val isStarted = AtomicBoolean(false)
|
private val isStarted = AtomicBoolean(false)
|
||||||
private val isReady = AtomicBoolean(false)
|
private val isReady = AtomicBoolean(false)
|
||||||
private val mainHandler = Handler(Looper.getMainLooper())
|
private val mainHandler = createUIHandler()
|
||||||
private val backgroundRealm = AtomicReference<Realm>()
|
private val backgroundRealm = AtomicReference<Realm>()
|
||||||
private val cancelableBag = CancelableBag()
|
private val cancelableBag = CancelableBag()
|
||||||
private val debouncer = Debouncer(mainHandler)
|
private val debouncer = Debouncer(mainHandler)
|
||||||
|
@ -22,17 +22,19 @@ import im.vector.matrix.android.internal.database.RealmLiveEntityObserver
|
|||||||
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.EventEntityFields
|
import im.vector.matrix.android.internal.database.model.EventEntityFields
|
||||||
import im.vector.matrix.android.internal.database.query.where
|
import im.vector.matrix.android.internal.database.query.where
|
||||||
|
import im.vector.matrix.android.internal.di.SessionDatabase
|
||||||
import im.vector.matrix.android.internal.session.SessionScope
|
import im.vector.matrix.android.internal.session.SessionScope
|
||||||
import im.vector.matrix.android.internal.task.TaskExecutor
|
import im.vector.matrix.android.internal.task.TaskExecutor
|
||||||
import im.vector.matrix.android.internal.task.TaskThread
|
import im.vector.matrix.android.internal.task.TaskThread
|
||||||
import im.vector.matrix.android.internal.task.configureWith
|
import im.vector.matrix.android.internal.task.configureWith
|
||||||
|
import io.realm.RealmConfiguration
|
||||||
import io.realm.Sort
|
import io.realm.Sort
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
internal class UserEntityUpdater @Inject constructor(monarchy: Monarchy,
|
internal class UserEntityUpdater @Inject constructor(@SessionDatabase realmConfiguration: RealmConfiguration,
|
||||||
private val updateUserTask: UpdateUserTask,
|
private val updateUserTask: UpdateUserTask,
|
||||||
private val taskExecutor: TaskExecutor)
|
private val taskExecutor: TaskExecutor)
|
||||||
: RealmLiveEntityObserver<EventEntity>(monarchy) {
|
: RealmLiveEntityObserver<EventEntity>(realmConfiguration) {
|
||||||
|
|
||||||
override val query = Monarchy.Query<EventEntity> {
|
override val query = Monarchy.Query<EventEntity> {
|
||||||
EventEntity
|
EventEntity
|
||||||
|
@ -0,0 +1,29 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2019 New Vector Ltd
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package im.vector.matrix.android.internal.util
|
||||||
|
|
||||||
|
import android.os.Handler
|
||||||
|
import android.os.HandlerThread
|
||||||
|
import android.os.Looper
|
||||||
|
|
||||||
|
fun createBackgroundHandler(name: String): Handler = Handler(
|
||||||
|
HandlerThread(name).apply { start() }.looper
|
||||||
|
)
|
||||||
|
|
||||||
|
fun createUIHandler(): Handler = Handler(
|
||||||
|
Looper.getMainLooper()
|
||||||
|
)
|
Loading…
Reference in New Issue
Block a user