Commit 6d66aed1 authored by Geoffrey Métais's avatar Geoffrey Métais

Close actors before cancelling parent job

parent 22a7124b
......@@ -27,9 +27,7 @@ import android.os.Handler
import android.os.HandlerThread
import android.os.Process
import android.support.v4.util.SimpleArrayMap
import android.util.Log
import kotlinx.coroutines.experimental.*
import kotlinx.coroutines.experimental.android.Main
import kotlinx.coroutines.experimental.channels.Channel
import kotlinx.coroutines.experimental.channels.actor
import kotlinx.coroutines.experimental.channels.mapTo
......@@ -61,11 +59,11 @@ abstract class BrowserProvider(val context: Context, val dataset: LiveDataset<Me
internal val medialibrary = Medialibrary.getInstance()
private val browserActor = actor<BrowserAction>(Dispatchers.IO, Channel.UNLIMITED) {
for (action in channel) when (action) {
for (action in channel) if (isActive) when (action) {
is Browse -> browseImpl(action.url)
is Refresh -> refreshImpl()
is ParseSubDirectories -> parseSubDirectoriesImpl()
}
} else channel.close()
}
init {
......@@ -93,7 +91,7 @@ abstract class BrowserProvider(val context: Context, val dataset: LiveDataset<Me
}
protected open fun browse(url: String? = null) {
browserActor.offer(Browse(url))
if (!browserActor.isClosedForSend) browserActor.offer(Browse(url))
}
private fun browseImpl(url: String? = null) {
......@@ -109,13 +107,13 @@ abstract class BrowserProvider(val context: Context, val dataset: LiveDataset<Me
protected open fun addMedia(media: MediaLibraryItem) = dataset.add(media)
open fun refresh() : Boolean {
if (url === null) return false
if (url === null || browserActor.isClosedForSend) return false
browserActor.offer(Refresh)
return true
}
internal open fun parseSubDirectories() {
browserActor.offer(ParseSubDirectories)
if (!browserActor.isClosedForSend) browserActor.offer(ParseSubDirectories)
}
open fun refreshImpl() {
......@@ -220,12 +218,15 @@ abstract class BrowserProvider(val context: Context, val dataset: LiveDataset<Me
fun stop() = job?.cancel()
open fun release() = launch(Dispatchers.IO) {
if (this@BrowserProvider::browserChannel.isInitialized) browserChannel.close()
job?.cancelAndJoin()
mediabrowser?.let {
it.release()
mediabrowser = null
open fun release() {
browserActor.close()
launch(Dispatchers.IO) {
if (this@BrowserProvider::browserChannel.isInitialized) browserChannel.close()
job?.cancelAndJoin()
mediabrowser?.let {
it.release()
mediabrowser = null
}
}
}
......
......@@ -25,7 +25,10 @@ import android.content.Context
import android.hardware.usb.UsbDevice
import android.net.Uri
import android.text.TextUtils
import kotlinx.coroutines.experimental.*
import kotlinx.coroutines.experimental.Dispatchers
import kotlinx.coroutines.experimental.cancelAndJoin
import kotlinx.coroutines.experimental.launch
import kotlinx.coroutines.experimental.withContext
import org.videolan.libvlc.util.AndroidUtil
import org.videolan.medialibrary.media.DummyItem
import org.videolan.medialibrary.media.MediaLibraryItem
......@@ -133,12 +136,12 @@ open class FileBrowserProvider(
}
}
override fun release(): Job {
override fun release() {
if (url == null) {
ExternalMonitor.devices.removeObserver(this)
if (showFavorites) favorites?.removeObserver(favoritesObserver)
}
return super.release()
super.release()
}
override fun onChanged(list: MutableList<UsbDevice>?) {
......
......@@ -22,15 +22,12 @@ package org.videolan.vlc.providers
import android.arch.lifecycle.Observer
import android.content.Context
import kotlinx.coroutines.experimental.Job
import kotlinx.coroutines.experimental.android.UI
import kotlinx.coroutines.experimental.launch
import org.videolan.medialibrary.media.DummyItem
import org.videolan.medialibrary.media.MediaLibraryItem
import org.videolan.medialibrary.media.MediaWrapper
import org.videolan.vlc.ExternalMonitor
import org.videolan.vlc.R
import org.videolan.vlc.database.MediaDatabase
import org.videolan.vlc.repository.BrowserFavRepository
import org.videolan.vlc.util.LiveDataset
......@@ -62,9 +59,9 @@ class NetworkProvider(context: Context, dataset: LiveDataset<MediaLibraryItem>,
if (url != null) super.parseSubDirectories()
}
override fun release(): Job {
override fun release() {
favorites?.removeObserver(this)
return super.release()
super.release()
}
override fun onChanged(favs: List<MediaWrapper>?) {
......
......@@ -23,9 +23,9 @@ package org.videolan.vlc.viewmodels
import android.arch.lifecycle.MediatorLiveData
import android.content.Context
import kotlinx.coroutines.experimental.Dispatchers
import kotlinx.coroutines.experimental.android.UI
import kotlinx.coroutines.experimental.channels.Channel
import kotlinx.coroutines.experimental.channels.actor
import kotlinx.coroutines.experimental.isActive
import kotlinx.coroutines.experimental.launch
import kotlinx.coroutines.experimental.withContext
import org.videolan.medialibrary.media.MediaLibraryItem
......@@ -64,28 +64,35 @@ abstract class BaseModel<T : MediaLibraryItem>(context: Context) : SortableModel
@Suppress("UNCHECKED_CAST")
protected val updateActor by lazy {
actor<Update>(capacity = Channel.UNLIMITED) {
for (update in channel) when (update) {
for (update in channel) if (isActive) when (update) {
Refresh -> updateList()
is Filter -> filter.filter(update.query)
is MediaUpdate -> updateItems(update.mediaList as List<T>)
is MediaAddition -> addMedia(update.media as T)
is MediaListAddition -> addMedia(update.mediaList as List<T>)
is Remove -> removeMedia(update.media as T)
}
} else channel.close()
}
}
override fun refresh() = updateActor.offer(Refresh)
override fun refresh() : Boolean {
if (!updateActor.isClosedForSend) updateActor.offer(Refresh)
return true
}
fun remove(mw: T) = updateActor.offer(Remove(mw))
fun remove(mw: T) {
if (!updateActor.isClosedForSend) updateActor.offer(Remove(mw))
}
override fun filter(query: String?) {
filtering = true
updateActor.offer(Filter(query))
if (!updateActor.isClosedForSend) {
filtering = true
updateActor.offer(Filter(query))
}
}
override fun restore() {
if (filtering) updateActor.offer(Filter(null))
if (filtering && !updateActor.isClosedForSend) updateActor.offer(Filter(null))
filtering = false
}
......@@ -113,6 +120,11 @@ abstract class BaseModel<T : MediaLibraryItem>(context: Context) : SortableModel
protected open suspend fun updateList() {}
protected abstract fun fetch()
override fun onCleared() {
updateActor.close()
super.onCleared()
}
}
sealed class Update
......
......@@ -3,12 +3,11 @@ package org.videolan.vlc.viewmodels
import android.arch.lifecycle.ViewModel
import kotlinx.coroutines.experimental.CoroutineScope
import kotlinx.coroutines.experimental.Dispatchers
import kotlinx.coroutines.experimental.Job
import kotlinx.coroutines.experimental.android.Main
import kotlinx.coroutines.experimental.SupervisorJob
open class ScopedModel : ViewModel(), CoroutineScope {
protected val job = Job()
protected val job = SupervisorJob()
override val coroutineContext = Dispatchers.Main.immediate+job
override fun onCleared() {
......
......@@ -27,7 +27,7 @@ import android.arch.lifecycle.ViewModelProviders
import android.content.Context
import android.support.v4.app.Fragment
import kotlinx.coroutines.experimental.Dispatchers
import kotlinx.coroutines.experimental.IO
import kotlinx.coroutines.experimental.isActive
import kotlinx.coroutines.experimental.withContext
import org.videolan.medialibrary.Medialibrary
import org.videolan.medialibrary.media.MediaWrapper
......@@ -42,7 +42,7 @@ open class VideosModel(context: Context, private val group: String?, private val
override fun canSortByDuration() = true
override fun canSortByLastModified() = true
private val thumbObs = Observer<MediaWrapper> { media -> updateActor.offer(MediaUpdate(listOf(media!!))) }
private val thumbObs = Observer<MediaWrapper> { media -> if (!updateActor.isClosedForSend) updateActor.offer(MediaUpdate(listOf(media!!))) }
init {
sort = if (customSort != Medialibrary.SORT_DEFAULT) customSort
......@@ -64,7 +64,9 @@ open class VideosModel(context: Context, private val group: String?, private val
}
override suspend fun updateList() {
if (!isActive) return
dataset.value = withContext(Dispatchers.IO) {
if (!isActive) return@withContext mutableListOf<MediaWrapper>()
val list = medialibrary.getVideos(sort, desc)
val displayList = mutableListOf<MediaWrapper>()
when {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment