Fixes to CoroutineScope

This includes removing what I thought was a good helper method for a list of preferences

Also using a base scope for controllers (others will have to be updated later)
This commit is contained in:
Jays2Kings 2021-04-26 05:29:12 -04:00
parent 8753d188d1
commit 0b4019a1cb
9 changed files with 50 additions and 56 deletions

View File

@ -43,17 +43,6 @@ fun <T> com.tfcporciuncula.flow.Preference<T>.asImmediateFlowIn(scope: Coroutine
.launchIn(scope) .launchIn(scope)
} }
fun <T> Collection<com.tfcporciuncula.flow.Preference<out T>>.asFlowsIn(scope: CoroutineScope, dropFirst: Boolean = false, block: () -> Unit): Collection<Job> {
return map { pref ->
pref.asFlow()
.apply {
if (dropFirst) drop(1)
}
.onEach { block() }
.launchIn(scope)
}
}
fun com.tfcporciuncula.flow.Preference<Boolean>.toggle() = set(!get()) fun com.tfcporciuncula.flow.Preference<Boolean>.toggle() = set(!get())
private class DateFormatConverter : Preference.Adapter<DateFormat> { private class DateFormatConverter : Preference.Adapter<DateFormat> {

View File

@ -13,12 +13,16 @@ import com.bluelinelabs.conductor.ControllerChangeHandler
import com.bluelinelabs.conductor.ControllerChangeType import com.bluelinelabs.conductor.ControllerChangeType
import com.bluelinelabs.conductor.RestoreViewOnCreateController import com.bluelinelabs.conductor.RestoreViewOnCreateController
import eu.kanade.tachiyomi.util.view.removeQueryListener import eu.kanade.tachiyomi.util.view.removeQueryListener
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.MainScope
import kotlinx.coroutines.cancel
import timber.log.Timber import timber.log.Timber
abstract class BaseController<VB : ViewBinding>(bundle: Bundle? = null) : abstract class BaseController<VB : ViewBinding>(bundle: Bundle? = null) :
RestoreViewOnCreateController(bundle) { RestoreViewOnCreateController(bundle) {
lateinit var binding: VB lateinit var binding: VB
lateinit var viewScope: CoroutineScope
val isBindingInitialized get() = this::binding.isInitialized val isBindingInitialized get() = this::binding.isInitialized
init { init {
@ -29,6 +33,7 @@ abstract class BaseController<VB : ViewBinding>(bundle: Bundle? = null) :
} }
override fun preCreateView(controller: Controller) { override fun preCreateView(controller: Controller) {
viewScope = MainScope()
Timber.d("Create view for ${controller.instance()}") Timber.d("Create view for ${controller.instance()}")
} }
@ -41,6 +46,7 @@ abstract class BaseController<VB : ViewBinding>(bundle: Bundle? = null) :
} }
override fun preDestroyView(controller: Controller, view: View) { override fun preDestroyView(controller: Controller, view: View) {
viewScope.cancel()
Timber.d("Destroy view for ${controller.instance()}") Timber.d("Destroy view for ${controller.instance()}")
} }
} }

View File

@ -46,7 +46,6 @@ import eu.kanade.tachiyomi.util.view.openInBrowser
import eu.kanade.tachiyomi.util.view.scrollViewWith import eu.kanade.tachiyomi.util.view.scrollViewWith
import eu.kanade.tachiyomi.util.view.snack import eu.kanade.tachiyomi.util.view.snack
import eu.kanade.tachiyomi.widget.preference.ListMatPreference import eu.kanade.tachiyomi.widget.preference.ListMatPreference
import kotlinx.coroutines.MainScope
import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.onEach
import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.Injekt
@ -64,7 +63,6 @@ class ExtensionDetailsController(bundle: Bundle? = null) :
private val preferences: PreferencesHelper = Injekt.get() private val preferences: PreferencesHelper = Injekt.get()
private val viewScope = MainScope()
init { init {
setHasOptionsMenu(true) setHasOptionsMenu(true)
} }

View File

@ -28,7 +28,6 @@ import androidx.coordinatorlayout.widget.CoordinatorLayout
import androidx.core.view.GestureDetectorCompat import androidx.core.view.GestureDetectorCompat
import androidx.core.view.isInvisible import androidx.core.view.isInvisible
import androidx.core.view.isVisible import androidx.core.view.isVisible
import androidx.recyclerview.widget.DefaultItemAnimator
import androidx.recyclerview.widget.GridLayoutManager import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.ItemTouchHelper import androidx.recyclerview.widget.ItemTouchHelper
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
@ -53,7 +52,6 @@ import eu.kanade.tachiyomi.data.library.LibraryUpdateService
import eu.kanade.tachiyomi.data.notification.NotificationReceiver import eu.kanade.tachiyomi.data.notification.NotificationReceiver
import eu.kanade.tachiyomi.data.notification.Notifications import eu.kanade.tachiyomi.data.notification.Notifications
import eu.kanade.tachiyomi.data.preference.PreferencesHelper import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.data.preference.asFlowsIn
import eu.kanade.tachiyomi.data.preference.getOrDefault import eu.kanade.tachiyomi.data.preference.getOrDefault
import eu.kanade.tachiyomi.databinding.LibraryControllerBinding import eu.kanade.tachiyomi.databinding.LibraryControllerBinding
import eu.kanade.tachiyomi.source.LocalSource import eu.kanade.tachiyomi.source.LocalSource
@ -99,11 +97,11 @@ import eu.kanade.tachiyomi.util.view.updateLayoutParams
import eu.kanade.tachiyomi.util.view.updatePaddingRelative import eu.kanade.tachiyomi.util.view.updatePaddingRelative
import eu.kanade.tachiyomi.util.view.withFadeTransaction import eu.kanade.tachiyomi.util.view.withFadeTransaction
import eu.kanade.tachiyomi.widget.EndAnimatorListener import eu.kanade.tachiyomi.widget.EndAnimatorListener
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.cancel import kotlinx.coroutines.cancel
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.drop
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get import uy.kohesive.injekt.api.get
import java.util.Locale import java.util.Locale
@ -150,8 +148,6 @@ class LibraryController(
var singleCategory: Boolean = false var singleCategory: Boolean = false
private set private set
val scope = CoroutineScope(Job() + Dispatchers.Main)
/** /**
* Library search query. * Library search query.
*/ */
@ -835,8 +831,13 @@ class LibraryController(
preferences.uniformGrid(), preferences.uniformGrid(),
preferences.gridSize(), preferences.gridSize(),
preferences.unreadBadgeType() preferences.unreadBadgeType()
).asFlowsIn(scope, true) { ).forEach {
reattachAdapter() it.asFlow()
.drop(1)
.onEach {
reattachAdapter()
}
.launchIn(viewScope)
} }
} }
@ -885,7 +886,6 @@ class LibraryController(
override fun onDestroy() { override fun onDestroy() {
if (::presenter.isInitialized) presenter.onDestroy() if (::presenter.isInitialized) presenter.onDestroy()
scope.cancel()
super.onDestroy() super.onDestroy()
} }
@ -897,6 +897,7 @@ class LibraryController(
} }
displaySheet?.dismiss() displaySheet?.dismiss()
displaySheet = null displaySheet = null
presenter.cancelScope()
super.onDestroyView(view) super.onDestroyView(view)
} }
@ -913,11 +914,6 @@ class LibraryController(
) )
} }
adapter.setItems(mangaMap) adapter.setItems(mangaMap)
if (binding.libraryGridRecycler.recycler.itemAnimator == null) {
binding.libraryGridRecycler.recycler.post {
binding.libraryGridRecycler.recycler.itemAnimator = DefaultItemAnimator()
}
}
singleCategory = presenter.categories.size <= 1 singleCategory = presenter.categories.size <= 1
showDropdown() showDropdown()
binding.progress.isVisible = false binding.progress.isVisible = false
@ -951,9 +947,7 @@ class LibraryController(
listOf(activityBinding?.toolbar, binding.headerTitle).forEach { listOf(activityBinding?.toolbar, binding.headerTitle).forEach {
it?.setOnClickListener { it?.setOnClickListener {
val recycler = binding.libraryGridRecycler.recycler val recycler = binding.libraryGridRecycler.recycler
if (singleCategory) { if (!singleCategory) {
recycler.scrollToPosition(0)
} else {
showCategories(recycler.translationY == 0f) showCategories(recycler.translationY == 0f)
} }
} }

View File

@ -33,6 +33,7 @@ import eu.kanade.tachiyomi.util.system.executeOnIO
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job import kotlinx.coroutines.Job
import kotlinx.coroutines.cancel
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.Injekt
@ -86,6 +87,10 @@ class LibraryPresenter(
val libraryIsGrouped val libraryIsGrouped
get() = groupType != UNGROUPED get() = groupType != UNGROUPED
fun cancelScope() {
scope.cancel()
}
/** Save the current list to speed up loading later */ /** Save the current list to speed up loading later */
fun onDestroy() { fun onDestroy() {
lastLibraryItems = libraryItems lastLibraryItems = libraryItems
@ -105,6 +110,7 @@ class LibraryPresenter(
if (categories.isEmpty()) { if (categories.isEmpty()) {
categories = lastCategories ?: db.getCategories().executeAsBlocking().toMutableList() categories = lastCategories ?: db.getCategories().executeAsBlocking().toMutableList()
} }
scope = CoroutineScope(Job() + Dispatchers.Default)
scope.launch { scope.launch {
val library = withContext(Dispatchers.IO) { getLibraryFromDB() } val library = withContext(Dispatchers.IO) { getLibraryFromDB() }
library.apply { library.apply {

View File

@ -181,7 +181,7 @@ class FilterBottomSheet @JvmOverloads constructor(context: Context, attrs: Attri
filterOrder = it filterOrder = it
clearFilters() clearFilters()
} }
.launchIn(controller.scope) .launchIn(controller.viewScope)
} }
private fun stateChanged(state: Int) { private fun stateChanged(state: Int) {

View File

@ -37,7 +37,6 @@ import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.database.models.Chapter import eu.kanade.tachiyomi.data.database.models.Chapter
import eu.kanade.tachiyomi.data.database.models.Manga import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.data.preference.PreferencesHelper import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.data.preference.asFlowsIn
import eu.kanade.tachiyomi.data.preference.asImmediateFlowIn import eu.kanade.tachiyomi.data.preference.asImmediateFlowIn
import eu.kanade.tachiyomi.data.preference.toggle import eu.kanade.tachiyomi.data.preference.toggle
import eu.kanade.tachiyomi.databinding.ReaderActivityBinding import eu.kanade.tachiyomi.databinding.ReaderActivityBinding
@ -637,7 +636,11 @@ class ReaderActivity :
} }
listOf(preferences.cropBorders(), preferences.cropBordersWebtoon()) listOf(preferences.cropBorders(), preferences.cropBordersWebtoon())
.asFlowsIn(scope) { updateCropBordersShortcut() } .forEach { pref ->
pref.asFlow()
.onEach { updateCropBordersShortcut() }
.launchIn(scope)
}
preferences.rotation().asImmediateFlowIn(scope) { updateRotationShortcut(it) } preferences.rotation().asImmediateFlowIn(scope) { updateRotationShortcut(it) }
binding.chaptersSheet.shiftPageButton.setOnClickListener { binding.chaptersSheet.shiftPageButton.setOnClickListener {

View File

@ -54,10 +54,6 @@ import eu.kanade.tachiyomi.util.view.snack
import eu.kanade.tachiyomi.util.view.updateLayoutParams import eu.kanade.tachiyomi.util.view.updateLayoutParams
import eu.kanade.tachiyomi.util.view.updatePaddingRelative import eu.kanade.tachiyomi.util.view.updatePaddingRelative
import eu.kanade.tachiyomi.util.view.withFadeTransaction import eu.kanade.tachiyomi.util.view.withFadeTransaction
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.cancel
import java.util.Locale import java.util.Locale
import kotlin.math.abs import kotlin.math.abs
import kotlin.math.max import kotlin.math.max
@ -89,12 +85,10 @@ class RecentsController(bundle: Bundle? = null) :
presenter.toggleGroupRecents(viewType, false) presenter.toggleGroupRecents(viewType, false)
} }
private val adapterScope: CoroutineScope = CoroutineScope(Job() + Dispatchers.Main)
/** /**
* Adapter containing the recent manga. * Adapter containing the recent manga.
*/ */
private var adapter = RecentMangaAdapter(this) private lateinit var adapter: RecentMangaAdapter
var displaySheet: TabbedRecentsOptionsSheet? = null var displaySheet: TabbedRecentsOptionsSheet? = null
private var progressItem: ProgressItem? = null private var progressItem: ProgressItem? = null
@ -383,14 +377,13 @@ class RecentsController(bundle: Bundle? = null) :
snack?.dismiss() snack?.dismiss()
presenter.onDestroy() presenter.onDestroy()
snack = null snack = null
adapterScope.cancel()
presenter.cancelScope()
} }
override fun onDestroyView(view: View) { override fun onDestroyView(view: View) {
super.onDestroyView(view) super.onDestroyView(view)
displaySheet?.dismiss() displaySheet?.dismiss()
displaySheet = null displaySheet = null
presenter.cancelScope()
} }
fun refresh() = presenter.getRecents() fun refresh() = presenter.getRecents()
@ -497,7 +490,7 @@ class RecentsController(bundle: Bundle? = null) :
override fun getViewType(): Int = presenter.viewType override fun getViewType(): Int = presenter.viewType
override fun scope() = adapterScope override fun scope() = viewScope
override fun onItemClick(view: View?, position: Int): Boolean { override fun onItemClick(view: View?, position: Int): Boolean {
val item = adapter.getItem(position) ?: return false val item = adapter.getItem(position) ?: return false

View File

@ -12,13 +12,15 @@ import eu.kanade.tachiyomi.data.download.model.DownloadQueue
import eu.kanade.tachiyomi.data.library.LibraryServiceListener import eu.kanade.tachiyomi.data.library.LibraryServiceListener
import eu.kanade.tachiyomi.data.library.LibraryUpdateService import eu.kanade.tachiyomi.data.library.LibraryUpdateService
import eu.kanade.tachiyomi.data.preference.PreferencesHelper import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.data.preference.asFlowsIn
import eu.kanade.tachiyomi.source.SourceManager import eu.kanade.tachiyomi.source.SourceManager
import eu.kanade.tachiyomi.util.system.executeOnIO import eu.kanade.tachiyomi.util.system.executeOnIO
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job import kotlinx.coroutines.Job
import kotlinx.coroutines.cancel import kotlinx.coroutines.cancel
import kotlinx.coroutines.flow.drop
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.Injekt
@ -71,17 +73,6 @@ class RecentsPresenter(
private val isOnFirstPage: Boolean private val isOnFirstPage: Boolean
get() = pageOffset == 0 get() = pageOffset == 0
init {
listOf(
preferences.groupChaptersHistory(),
preferences.showReadInAllRecents(),
preferences.groupChaptersUpdates()
).asFlowsIn(scope, true) {
resetOffsets()
getRecents()
}
}
fun onCreate() { fun onCreate() {
downloadManager.addListener(this) downloadManager.addListener(this)
LibraryUpdateService.setListener(this) LibraryUpdateService.setListener(this)
@ -92,6 +83,20 @@ class RecentsPresenter(
lastRecents = null lastRecents = null
} }
getRecents() getRecents()
scope = CoroutineScope(Job() + Dispatchers.Default)
listOf(
preferences.groupChaptersHistory(),
preferences.showReadInAllRecents(),
preferences.groupChaptersUpdates()
).forEach {
it.asFlow()
.drop(1)
.onEach {
resetOffsets()
getRecents()
}
.launchIn(scope)
}
} }
fun getRecents(updatePageCount: Boolean = false) { fun getRecents(updatePageCount: Boolean = false) {