Sync: add progress indicator for sync, need UI inputs.

This commit is contained in:
ganfra
2019-06-11 16:54:44 +02:00
parent 6323183119
commit 3dd161d65a
9 changed files with 123 additions and 39 deletions

View File

@ -17,6 +17,7 @@
package im.vector.matrix.android.api.session
import androidx.annotation.MainThread
import androidx.lifecycle.LiveData
import im.vector.matrix.android.api.auth.data.SessionParams
import im.vector.matrix.android.api.session.cache.CacheService
import im.vector.matrix.android.api.session.content.ContentUploadStateTracker
@ -27,6 +28,7 @@ import im.vector.matrix.android.api.session.room.RoomDirectoryService
import im.vector.matrix.android.api.session.room.RoomService
import im.vector.matrix.android.api.session.signout.SignOutService
import im.vector.matrix.android.api.session.sync.FilterService
import im.vector.matrix.android.api.session.sync.SyncState
import im.vector.matrix.android.api.session.user.UserService
/**
@ -66,6 +68,12 @@ interface Session :
@MainThread
fun stopSync()
/**
* This method allows to listen the sync state.
* @return a [LiveData] of [SyncState].
*/
fun syncState(): LiveData<SyncState>
/**
* This method allow to close a session. It does stop some services.
*/
@ -102,6 +110,7 @@ interface Session :
* The access token is not valid anymore
*/
fun onInvalidToken()
}
}

View File

@ -0,0 +1,27 @@
/*
*
* * 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.api.session.sync
sealed class SyncState {
object IDLE : SyncState()
data class RUNNING(val catchingUp: Boolean) : SyncState()
object PAUSED : SyncState()
object KILLING : SyncState()
object KILLED : SyncState()
}

View File

@ -39,6 +39,7 @@ import im.vector.matrix.android.api.session.room.model.roomdirectory.PublicRooms
import im.vector.matrix.android.api.session.room.model.thirdparty.ThirdPartyProtocol
import im.vector.matrix.android.api.session.signout.SignOutService
import im.vector.matrix.android.api.session.sync.FilterService
import im.vector.matrix.android.api.session.sync.SyncState
import im.vector.matrix.android.api.session.user.UserService
import im.vector.matrix.android.api.session.user.model.User
import im.vector.matrix.android.api.util.Cancelable
@ -124,6 +125,10 @@ internal class DefaultSession(override val sessionParams: SessionParams) : Sessi
isOpen = false
}
override fun syncState(): LiveData<SyncState> {
return syncThread.liveState()
}
@MainThread
override fun signOut(callback: MatrixCallback<Unit>) {
assert(isOpen)

View File

@ -16,10 +16,13 @@
package im.vector.matrix.android.internal.session.sync.job
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import com.squareup.moshi.JsonEncodingException
import im.vector.matrix.android.api.MatrixCallback
import im.vector.matrix.android.api.failure.Failure
import im.vector.matrix.android.api.failure.MatrixError
import im.vector.matrix.android.api.session.sync.SyncState
import im.vector.matrix.android.api.util.Cancelable
import im.vector.matrix.android.internal.network.NetworkConnectivityChecker
import im.vector.matrix.android.internal.session.sync.SyncTask
@ -42,61 +45,52 @@ internal class SyncThread(private val syncTask: SyncTask,
private val taskExecutor: TaskExecutor
) : Thread(), NetworkConnectivityChecker.Listener, BackgroundDetectionObserver.Listener {
enum class State {
IDLE,
RUNNING,
PAUSED,
KILLING,
KILLED
}
private var state: State = State.IDLE
private var state: SyncState = SyncState.IDLE
private var liveState = MutableLiveData<SyncState>()
private val lock = Object()
private var nextBatch = syncTokenStore.getLastToken()
private var cancelableTask: Cancelable? = null
fun restart() {
synchronized(lock) {
if (state != State.PAUSED) {
return@synchronized
}
Timber.v("Resume sync...")
init {
updateStateTo(SyncState.IDLE)
}
fun restart() = synchronized(lock) {
if (state is SyncState.PAUSED) {
Timber.v("Resume sync...")
// Retrieve the last token, it may have been deleted in case of a clear cache
nextBatch = syncTokenStore.getLastToken()
state = State.RUNNING
updateStateTo(SyncState.RUNNING(catchingUp = true))
lock.notify()
}
}
fun pause() {
synchronized(lock) {
if (state != State.RUNNING) {
return@synchronized
}
fun pause() = synchronized(lock) {
if (state is SyncState.RUNNING) {
Timber.v("Pause sync...")
state = State.PAUSED
updateStateTo(SyncState.PAUSED)
}
}
fun kill() {
synchronized(lock) {
Timber.v("Kill sync...")
state = State.KILLING
cancelableTask?.cancel()
lock.notify()
}
fun kill() = synchronized(lock) {
Timber.v("Kill sync...")
updateStateTo(SyncState.KILLING)
cancelableTask?.cancel()
lock.notify()
}
fun liveState(): LiveData<SyncState> {
return liveState
}
override fun run() {
Timber.v("Start syncing...")
networkConnectivityChecker.register(this)
backgroundDetectionObserver.register(this)
state = State.RUNNING
while (state != State.KILLING) {
if (!networkConnectivityChecker.isConnected() || state == State.PAUSED) {
updateStateTo(SyncState.RUNNING(catchingUp = true))
while (state != SyncState.KILLING) {
if (!networkConnectivityChecker.isConnected() || state == SyncState.PAUSED) {
Timber.v("Waiting...")
synchronized(lock) {
lock.wait()
@ -133,7 +127,7 @@ internal class SyncThread(private val syncTask: SyncTask,
if (failure is Failure.ServerError
&& (failure.error.code == MatrixError.UNKNOWN_TOKEN || failure.error.code == MatrixError.MISSING_TOKEN)) {
// No token or invalid token, stop the thread
state = State.KILLING
updateStateTo(SyncState.KILLING)
}
latch.countDown()
@ -141,16 +135,23 @@ internal class SyncThread(private val syncTask: SyncTask,
})
.executeBy(taskExecutor)
latch.await()
if (state is SyncState.RUNNING) {
updateStateTo(SyncState.RUNNING(catchingUp = false))
}
}
}
Timber.v("Sync killed")
state = State.KILLED
updateStateTo(SyncState.KILLED)
backgroundDetectionObserver.unregister(this)
networkConnectivityChecker.unregister(this)
}
private fun updateStateTo(newState: SyncState) {
state = newState
liveState.postValue(newState)
}
override fun onConnect() {
synchronized(lock) {
lock.notify()