SyncThread: Fix issue when network is back and the app was in background: do not restart the thread

This commit is contained in:
Benoit Marty 2019-09-17 14:26:30 +02:00
parent 73ec0f5a83
commit 25e9a179d2
5 changed files with 30 additions and 27 deletions

View File

@ -36,7 +36,8 @@ internal class NetworkConnectivityChecker @Inject constructor(context: Context)
private val listeners = Collections.synchronizedSet(LinkedHashSet<Listener>()) private val listeners = Collections.synchronizedSet(LinkedHashSet<Listener>())
// True when internet is available // True when internet is available
private var hasInternetAccess = false var hasInternetAccess = false
private set
init { init {
merlin.bind() merlin.bind()
@ -63,7 +64,7 @@ internal class NetworkConnectivityChecker @Inject constructor(context: Context)
} }
suspend fun waitUntilConnected() { suspend fun waitUntilConnected() {
if (isConnected()) { if (hasInternetAccess) {
return return
} else { } else {
suspendCoroutine<Unit> { continuation -> suspendCoroutine<Unit> { continuation ->
@ -85,10 +86,6 @@ internal class NetworkConnectivityChecker @Inject constructor(context: Context)
listeners.remove(listener) listeners.remove(listener)
} }
fun isConnected(): Boolean {
return hasInternetAccess
}
interface Listener { interface Listener {
fun onConnect() { fun onConnect() {

View File

@ -93,8 +93,8 @@ open class SyncService : Service() {
} }
fun doSync(once: Boolean = false) { fun doSync(once: Boolean = false) {
if (!networkConnectivityChecker.isConnected()) { if (!networkConnectivityChecker.hasInternetAccess) {
Timber.v("Sync is Paused. Waiting...") Timber.v("No internet access. Waiting...")
//TODO Retry in ? //TODO Retry in ?
timer.schedule(object : TimerTask() { timer.schedule(object : TimerTask() {
override fun run() { override fun run() {

View File

@ -50,6 +50,8 @@ internal class SyncThread @Inject constructor(private val syncTask: SyncTask,
private val lock = Object() private val lock = Object()
private var cancelableTask: Cancelable? = null private var cancelableTask: Cancelable? = null
private var isStarted = false
init { init {
updateStateTo(SyncState.IDLE) updateStateTo(SyncState.IDLE)
} }
@ -60,19 +62,18 @@ internal class SyncThread @Inject constructor(private val syncTask: SyncTask,
} }
fun restart() = synchronized(lock) { fun restart() = synchronized(lock) {
if (state is SyncState.PAUSED) { if (!isStarted) {
Timber.v("Resume sync...") Timber.v("Resume sync...")
updateStateTo(SyncState.RUNNING(afterPause = true)) isStarted = true
lock.notify() lock.notify()
} }
} }
fun pause() = synchronized(lock) { fun pause() = synchronized(lock) {
if (state is SyncState.RUNNING) { if (isStarted) {
Timber.v("Pause sync...") Timber.v("Pause sync...")
updateStateTo(SyncState.PAUSED) isStarted = false
cancelableTask?.cancel() cancelableTask?.cancel()
lock.notify()
} }
} }
@ -87,21 +88,31 @@ internal class SyncThread @Inject constructor(private val syncTask: SyncTask,
return liveState return liveState
} }
override fun onConnect() {
Timber.v("Network is back")
synchronized(lock) {
lock.notify()
}
}
override fun run() { override fun run() {
Timber.v("Start syncing...") Timber.v("Start syncing...")
isStarted = true
networkConnectivityChecker.register(this) networkConnectivityChecker.register(this)
backgroundDetectionObserver.register(this) backgroundDetectionObserver.register(this)
while (state != SyncState.KILLING) { while (state != SyncState.KILLING) {
Timber.v("Entering loop, state: $state") Timber.v("Entering loop, state: $state")
if (!networkConnectivityChecker.isConnected() || state == SyncState.PAUSED) { if (!networkConnectivityChecker.hasInternetAccess) {
Timber.v("No network or sync is Paused. Waiting...") Timber.v("No network. Waiting...")
updateStateTo(SyncState.NO_NETWORK) updateStateTo(SyncState.NO_NETWORK)
synchronized(lock) { lock.wait() }
synchronized(lock) { Timber.v("...unlocked")
lock.wait() } else if (!isStarted) {
} Timber.v("Sync is Paused. Waiting...")
updateStateTo(SyncState.PAUSED)
synchronized(lock) { lock.wait() }
Timber.v("...unlocked") Timber.v("...unlocked")
} else { } else {
if (state !is SyncState.RUNNING) { if (state !is SyncState.RUNNING) {
@ -169,16 +180,11 @@ internal class SyncThread @Inject constructor(private val syncTask: SyncTask,
} }
private fun updateStateTo(newState: SyncState) { private fun updateStateTo(newState: SyncState) {
Timber.v("Update state to $newState") Timber.v("Update state from $state to $newState")
state = newState state = newState
liveState.postValue(newState) liveState.postValue(newState)
} }
override fun onConnect() {
synchronized(lock) {
lock.notify()
}
}
override fun onMoveToForeground() { override fun onMoveToForeground() {
restart() restart()

View File

@ -33,7 +33,7 @@ internal class BackgroundDetectionObserver @Inject constructor() : LifecycleObse
private set private set
private private
val listeners = ArrayList<Listener>() val listeners = LinkedHashSet<Listener>()
fun register(listener: Listener) { fun register(listener: Listener) {
listeners.add(listener) listeners.add(listener)

View File

@ -38,6 +38,6 @@ class SyncStateView @JvmOverloads constructor(context: Context, attrs: Attribute
is SyncState.RUNNING -> if (newState.afterPause) View.VISIBLE else View.GONE is SyncState.RUNNING -> if (newState.afterPause) View.VISIBLE else View.GONE
else -> View.GONE else -> View.GONE
} }
syncStateNoNetwork.isVisible = newState is SyncState.NO_NETWORK syncStateNoNetwork.isVisible = newState == SyncState.NO_NETWORK
} }
} }