forked from GitHub-Mirror/riotX-android
Better coroutines management
This commit is contained in:
parent
1a967b6326
commit
95fd7190e4
BIN
.idea/caches/build_file_checksums.ser
generated
BIN
.idea/caches/build_file_checksums.ser
generated
Binary file not shown.
5
.idea/codeStyles/codeStyleConfig.xml
generated
Normal file
5
.idea/codeStyles/codeStyleConfig.xml
generated
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
<component name="ProjectCodeStyleConfiguration">
|
||||||
|
<state>
|
||||||
|
<option name="PREFERRED_PROJECT_CODE_STYLE" value="Default" />
|
||||||
|
</state>
|
||||||
|
</component>
|
@ -1,7 +1,7 @@
|
|||||||
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
||||||
|
|
||||||
buildscript {
|
buildscript {
|
||||||
ext.kotlin_version = '1.3.0-rc-116'
|
ext.kotlin_version = '1.3.0-rc-146'
|
||||||
ext.koin_version = '1.0.1'
|
ext.koin_version = '1.0.1'
|
||||||
repositories {
|
repositories {
|
||||||
google()
|
google()
|
||||||
@ -9,7 +9,7 @@ buildscript {
|
|||||||
maven { url 'https://dl.bintray.com/kotlin/kotlin-eap' }
|
maven { url 'https://dl.bintray.com/kotlin/kotlin-eap' }
|
||||||
}
|
}
|
||||||
dependencies {
|
dependencies {
|
||||||
classpath 'com.android.tools.build:gradle:3.2.0'
|
classpath 'com.android.tools.build:gradle:3.2.1'
|
||||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||||
|
|
||||||
// NOTE: Do not place your application dependencies here; they belong
|
// NOTE: Do not place your application dependencies here; they belong
|
||||||
|
@ -4,7 +4,6 @@ import android.content.Context
|
|||||||
import im.vector.matrix.android.BuildConfig
|
import im.vector.matrix.android.BuildConfig
|
||||||
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.api.thread.MainThreadExecutor
|
|
||||||
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
|
||||||
@ -13,7 +12,6 @@ import org.koin.standalone.StandAloneContext.loadKoinModules
|
|||||||
import org.koin.standalone.inject
|
import org.koin.standalone.inject
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import timber.log.Timber.DebugTree
|
import timber.log.Timber.DebugTree
|
||||||
import java.util.concurrent.Executor
|
|
||||||
|
|
||||||
|
|
||||||
class Matrix(matrixOptions: MatrixOptions) : KoinComponent {
|
class Matrix(matrixOptions: MatrixOptions) : KoinComponent {
|
||||||
@ -38,5 +36,4 @@ class Matrix(matrixOptions: MatrixOptions) : KoinComponent {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
data class MatrixOptions(val context: Context,
|
data class MatrixOptions(val context: Context)
|
||||||
val mainExecutor: Executor = MainThreadExecutor())
|
|
||||||
|
@ -18,7 +18,7 @@ class AuthModule(private val context: Context) : Module {
|
|||||||
override fun invoke(): ModuleDefinition = module {
|
override fun invoke(): ModuleDefinition = module {
|
||||||
|
|
||||||
single {
|
single {
|
||||||
DefaultAuthenticator(get(), get(), get(), get()) as Authenticator
|
DefaultAuthenticator(get(), get(), get()) as Authenticator
|
||||||
}
|
}
|
||||||
|
|
||||||
single(name = AUTH_BOX_STORE) {
|
single(name = AUTH_BOX_STORE) {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
package im.vector.matrix.android.internal.auth
|
package im.vector.matrix.android.internal.auth
|
||||||
|
|
||||||
|
import arrow.core.Either
|
||||||
import arrow.core.leftIfNull
|
import arrow.core.leftIfNull
|
||||||
import com.squareup.moshi.Moshi
|
|
||||||
import im.vector.matrix.android.api.MatrixCallback
|
import im.vector.matrix.android.api.MatrixCallback
|
||||||
import im.vector.matrix.android.api.auth.Authenticator
|
import im.vector.matrix.android.api.auth.Authenticator
|
||||||
import im.vector.matrix.android.api.auth.data.HomeServerConnectionConfig
|
import im.vector.matrix.android.api.auth.data.HomeServerConnectionConfig
|
||||||
@ -17,10 +17,10 @@ import im.vector.matrix.android.internal.util.CancelableCoroutine
|
|||||||
import im.vector.matrix.android.internal.util.MatrixCoroutineDispatchers
|
import im.vector.matrix.android.internal.util.MatrixCoroutineDispatchers
|
||||||
import kotlinx.coroutines.GlobalScope
|
import kotlinx.coroutines.GlobalScope
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
import retrofit2.Retrofit
|
import retrofit2.Retrofit
|
||||||
|
|
||||||
class DefaultAuthenticator(private val retrofitBuilder: Retrofit.Builder,
|
class DefaultAuthenticator(private val retrofitBuilder: Retrofit.Builder,
|
||||||
private val jsonMapper: Moshi,
|
|
||||||
private val coroutineDispatchers: MatrixCoroutineDispatchers,
|
private val coroutineDispatchers: MatrixCoroutineDispatchers,
|
||||||
private val sessionParamsStore: SessionParamsStore) : Authenticator {
|
private val sessionParamsStore: SessionParamsStore) : Authenticator {
|
||||||
|
|
||||||
@ -35,28 +35,37 @@ class DefaultAuthenticator(private val retrofitBuilder: Retrofit.Builder,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun authenticate(homeServerConnectionConfig: HomeServerConnectionConfig, login: String, password: String, callback: MatrixCallback<Session>): Cancelable {
|
override fun authenticate(homeServerConnectionConfig: HomeServerConnectionConfig,
|
||||||
val authAPI = buildAuthAPI(homeServerConnectionConfig)
|
login: String,
|
||||||
|
password: String,
|
||||||
|
callback: MatrixCallback<Session>): Cancelable {
|
||||||
|
|
||||||
val job = GlobalScope.launch(coroutineDispatchers.main) {
|
val job = GlobalScope.launch(coroutineDispatchers.main) {
|
||||||
val loginParams = PasswordLoginParams.userIdentifier(login, password, "Mobile")
|
val sessionOrFailure = authenticate(homeServerConnectionConfig, login, password)
|
||||||
executeRequest<Credentials> {
|
sessionOrFailure.bimap({ callback.onFailure(it) }, { callback.onSuccess(it) })
|
||||||
apiCall = authAPI.login(loginParams)
|
|
||||||
moshi = jsonMapper
|
|
||||||
dispatcher = coroutineDispatchers.io
|
|
||||||
}.leftIfNull {
|
|
||||||
Failure.Unknown(IllegalArgumentException("Credentials shouldn't not be null"))
|
|
||||||
}.map {
|
|
||||||
val sessionParams = SessionParams(it, homeServerConnectionConfig)
|
|
||||||
sessionParamsStore.save(sessionParams)
|
|
||||||
sessionParams
|
|
||||||
}.map {
|
|
||||||
DefaultSession(it)
|
|
||||||
}.bimap(
|
|
||||||
{ callback.onFailure(it) }, { callback.onSuccess(it) }
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
return CancelableCoroutine(job)
|
return CancelableCoroutine(job)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private suspend fun authenticate(homeServerConnectionConfig: HomeServerConnectionConfig,
|
||||||
|
login: String,
|
||||||
|
password: String): Either<Failure, Session> = withContext(coroutineDispatchers.io) {
|
||||||
|
|
||||||
|
val authAPI = buildAuthAPI(homeServerConnectionConfig)
|
||||||
|
val loginParams = PasswordLoginParams.userIdentifier(login, password, "Mobile")
|
||||||
|
executeRequest<Credentials> {
|
||||||
|
apiCall = authAPI.login(loginParams)
|
||||||
|
}.leftIfNull {
|
||||||
|
Failure.Unknown(IllegalArgumentException("Credentials shouldn't not be null"))
|
||||||
|
}.map {
|
||||||
|
val sessionParams = SessionParams(it, homeServerConnectionConfig)
|
||||||
|
sessionParamsStore.save(sessionParams)
|
||||||
|
sessionParams
|
||||||
|
}.map {
|
||||||
|
DefaultSession(it)
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun buildAuthAPI(homeServerConnectionConfig: HomeServerConnectionConfig): AuthAPI {
|
private fun buildAuthAPI(homeServerConnectionConfig: HomeServerConnectionConfig): AuthAPI {
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package im.vector.matrix.android.internal.di
|
package im.vector.matrix.android.internal.di
|
||||||
|
|
||||||
import im.vector.matrix.android.api.MatrixOptions
|
import im.vector.matrix.android.api.MatrixOptions
|
||||||
|
import im.vector.matrix.android.api.thread.MainThreadExecutor
|
||||||
import im.vector.matrix.android.internal.util.MatrixCoroutineDispatchers
|
import im.vector.matrix.android.internal.util.MatrixCoroutineDispatchers
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.IO
|
import kotlinx.coroutines.IO
|
||||||
@ -19,7 +20,7 @@ class MatrixModule(private val options: MatrixOptions) : Module {
|
|||||||
}
|
}
|
||||||
|
|
||||||
single {
|
single {
|
||||||
MatrixCoroutineDispatchers(io = Dispatchers.IO, computation = Dispatchers.IO, main = options.mainExecutor.asCoroutineDispatcher())
|
MatrixCoroutineDispatchers(io = Dispatchers.IO, computation = Dispatchers.IO, main = MainThreadExecutor().asCoroutineDispatcher())
|
||||||
}
|
}
|
||||||
}.invoke()
|
}.invoke()
|
||||||
}
|
}
|
@ -11,4 +11,4 @@ object MoshiProvider {
|
|||||||
return moshi
|
return moshi
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package im.vector.matrix.android.internal.events.sync
|
package im.vector.matrix.android.internal.events.sync
|
||||||
|
|
||||||
|
import im.vector.matrix.android.api.events.Event
|
||||||
import im.vector.matrix.android.internal.database.mapper.EventMapper
|
import im.vector.matrix.android.internal.database.mapper.EventMapper
|
||||||
import im.vector.matrix.android.internal.database.model.ChunkEntity
|
import im.vector.matrix.android.internal.database.model.ChunkEntity
|
||||||
import im.vector.matrix.android.internal.database.model.EventEntity
|
import im.vector.matrix.android.internal.database.model.EventEntity
|
||||||
@ -23,8 +24,8 @@ class RoomSyncHandler(
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
val roomEntities = ArrayList<RoomEntity>()
|
val roomEntities = ArrayList<RoomEntity>()
|
||||||
roomSyncByRoom.forEach { roomId, roomSync ->
|
roomSyncByRoom.forEach {
|
||||||
val roomEntity = handleJoinedRoom(roomId, roomSync)
|
val roomEntity = handleJoinedRoom(it.key, it.value)
|
||||||
roomEntities.add(roomEntity)
|
roomEntities.add(roomEntity)
|
||||||
}
|
}
|
||||||
roomBox.put(roomEntities)
|
roomBox.put(roomEntities)
|
||||||
@ -40,22 +41,27 @@ class RoomSyncHandler(
|
|||||||
}
|
}
|
||||||
roomEntity.membership = RoomEntity.Membership.JOINED
|
roomEntity.membership = RoomEntity.Membership.JOINED
|
||||||
if (roomSync.timeline != null) {
|
if (roomSync.timeline != null) {
|
||||||
val chunkEntity = ChunkEntity()
|
val chunkEntity = eventListToChunk(roomSync.timeline.events, roomSync.timeline.prevBatch)
|
||||||
chunkEntity.prevToken = roomSync.timeline.prevBatch
|
|
||||||
roomSync.timeline.events
|
|
||||||
.map { event -> EventMapper.map(event) }
|
|
||||||
.forEach { chunkEntity.events.add(it) }
|
|
||||||
roomEntity.chunks.add(chunkEntity)
|
roomEntity.chunks.add(chunkEntity)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (roomSync.state != null) {
|
if (roomSync.state != null) {
|
||||||
val chunkEntity = ChunkEntity()
|
val chunkEntity = eventListToChunk(roomSync.state.events)
|
||||||
roomSync.state.events
|
|
||||||
.map { event -> EventMapper.map(event) }
|
|
||||||
.forEach { chunkEntity.events.add(it) }
|
|
||||||
roomEntity.chunks.add(chunkEntity)
|
roomEntity.chunks.add(chunkEntity)
|
||||||
}
|
}
|
||||||
return roomEntity
|
return roomEntity
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun eventListToChunk(eventList: List<Event>,
|
||||||
|
prevToken: String? = null,
|
||||||
|
nextToken: String? = null): ChunkEntity {
|
||||||
|
val chunkEntity = ChunkEntity()
|
||||||
|
chunkEntity.prevToken = prevToken
|
||||||
|
chunkEntity.nextToken = nextToken
|
||||||
|
eventList
|
||||||
|
.map { event -> EventMapper.map(event) }
|
||||||
|
.forEach { chunkEntity.events.add(it) }
|
||||||
|
return chunkEntity
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -24,7 +24,7 @@ class SyncModule : Module {
|
|||||||
}
|
}
|
||||||
|
|
||||||
scope(DefaultSession.SCOPE) {
|
scope(DefaultSession.SCOPE) {
|
||||||
Synchronizer(get(), get(), get(), get())
|
Synchronizer(get(), get(), get())
|
||||||
}
|
}
|
||||||
|
|
||||||
}.invoke()
|
}.invoke()
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
package im.vector.matrix.android.internal.events.sync
|
package im.vector.matrix.android.internal.events.sync
|
||||||
|
|
||||||
import com.squareup.moshi.Moshi
|
|
||||||
import im.vector.matrix.android.api.MatrixCallback
|
import im.vector.matrix.android.api.MatrixCallback
|
||||||
import im.vector.matrix.android.api.util.Cancelable
|
import im.vector.matrix.android.api.util.Cancelable
|
||||||
import im.vector.matrix.android.internal.events.sync.data.SyncResponse
|
import im.vector.matrix.android.internal.events.sync.data.SyncResponse
|
||||||
@ -11,30 +10,32 @@ import im.vector.matrix.android.internal.util.CancelableCoroutine
|
|||||||
import im.vector.matrix.android.internal.util.MatrixCoroutineDispatchers
|
import im.vector.matrix.android.internal.util.MatrixCoroutineDispatchers
|
||||||
import kotlinx.coroutines.GlobalScope
|
import kotlinx.coroutines.GlobalScope
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
|
|
||||||
class Synchronizer(private val syncAPI: SyncAPI,
|
class Synchronizer(private val syncAPI: SyncAPI,
|
||||||
private val coroutineDispatchers: MatrixCoroutineDispatchers,
|
private val coroutineDispatchers: MatrixCoroutineDispatchers,
|
||||||
private val jsonMapper: Moshi,
|
|
||||||
private val syncResponseHandler: SyncResponseHandler) {
|
private val syncResponseHandler: SyncResponseHandler) {
|
||||||
|
|
||||||
fun synchronize(callback: MatrixCallback<SyncResponse>): Cancelable {
|
fun synchronize(callback: MatrixCallback<SyncResponse>): Cancelable {
|
||||||
val job = GlobalScope.launch(coroutineDispatchers.main) {
|
val job = GlobalScope.launch(coroutineDispatchers.main) {
|
||||||
val params = HashMap<String, String>()
|
val syncOrFailure = synchronize()
|
||||||
val filterBody = FilterBody()
|
syncOrFailure.bimap({ callback.onFailure(it) }, { callback.onSuccess(it) })
|
||||||
FilterUtil.enableLazyLoading(filterBody, true)
|
|
||||||
params["timeout"] = "0"
|
|
||||||
params["filter"] = filterBody.toJSONString()
|
|
||||||
val syncResponse = executeRequest<SyncResponse> {
|
|
||||||
apiCall = syncAPI.sync(params)
|
|
||||||
moshi = jsonMapper
|
|
||||||
dispatcher = coroutineDispatchers.io
|
|
||||||
}.map {
|
|
||||||
syncResponseHandler.handleResponse(it, null, false)
|
|
||||||
it
|
|
||||||
}
|
|
||||||
syncResponse.bimap({ callback.onFailure(it) }, { callback.onSuccess(it) })
|
|
||||||
}
|
}
|
||||||
return CancelableCoroutine(job)
|
return CancelableCoroutine(job)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private suspend fun synchronize() = withContext(coroutineDispatchers.io) {
|
||||||
|
val params = HashMap<String, String>()
|
||||||
|
val filterBody = FilterBody()
|
||||||
|
FilterUtil.enableLazyLoading(filterBody, true)
|
||||||
|
params["timeout"] = "0"
|
||||||
|
params["filter"] = filterBody.toJSONString()
|
||||||
|
executeRequest<SyncResponse> {
|
||||||
|
apiCall = syncAPI.sync(params)
|
||||||
|
}.map {
|
||||||
|
syncResponseHandler.handleResponse(it, null, false)
|
||||||
|
it
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -4,9 +4,9 @@ import arrow.core.Either
|
|||||||
import com.squareup.moshi.Moshi
|
import com.squareup.moshi.Moshi
|
||||||
import im.vector.matrix.android.api.failure.Failure
|
import im.vector.matrix.android.api.failure.Failure
|
||||||
import im.vector.matrix.android.api.failure.MatrixError
|
import im.vector.matrix.android.api.failure.MatrixError
|
||||||
import kotlinx.coroutines.CoroutineDispatcher
|
import im.vector.matrix.android.internal.di.MoshiProvider
|
||||||
import kotlinx.coroutines.Deferred
|
import kotlinx.coroutines.Deferred
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.coroutineScope
|
||||||
import okhttp3.ResponseBody
|
import okhttp3.ResponseBody
|
||||||
import retrofit2.Response
|
import retrofit2.Response
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
@ -15,13 +15,11 @@ suspend inline fun <DATA> executeRequest(block: Request<DATA>.() -> Unit) = Requ
|
|||||||
|
|
||||||
class Request<DATA> {
|
class Request<DATA> {
|
||||||
|
|
||||||
|
var moshi: Moshi = MoshiProvider.providesMoshi()
|
||||||
lateinit var apiCall: Deferred<Response<DATA>>
|
lateinit var apiCall: Deferred<Response<DATA>>
|
||||||
lateinit var moshi: Moshi
|
|
||||||
lateinit var dispatcher: CoroutineDispatcher
|
|
||||||
|
|
||||||
suspend fun execute(): Either<Failure, DATA?> = withContext(dispatcher) {
|
|
||||||
return@withContext try {
|
|
||||||
|
|
||||||
|
suspend fun execute(): Either<Failure, DATA?> = coroutineScope {
|
||||||
|
try {
|
||||||
val response = apiCall.await()
|
val response = apiCall.await()
|
||||||
if (response.isSuccessful) {
|
if (response.isSuccessful) {
|
||||||
val result = response.body()
|
val result = response.body()
|
||||||
|
Loading…
Reference in New Issue
Block a user