Create base coroutine classes for controller/presenters

Using so far for recents and extensions presenter
This commit is contained in:
Jays2Kings 2021-04-26 15:36:57 -04:00
parent f28419ce3f
commit a9125cc591
5 changed files with 67 additions and 38 deletions

View File

@ -0,0 +1,21 @@
package eu.kanade.tachiyomi.ui.base.controller
import android.os.Bundle
import android.view.View
import androidx.viewbinding.ViewBinding
import eu.kanade.tachiyomi.ui.base.presenter.BaseCoroutinePresenter
abstract class BaseCoroutineController<VB : ViewBinding, PS : BaseCoroutinePresenter>(bundle: Bundle? = null) :
BaseController<VB>(bundle) {
abstract val presenter: PS
override fun onViewCreated(view: View) {
super.onViewCreated(view)
presenter.onCreate()
}
override fun onDestroyView(view: View) {
super.onDestroyView(view)
presenter.onDestroy()
}
}

View File

@ -0,0 +1,18 @@
package eu.kanade.tachiyomi.ui.base.presenter
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.cancel
open class BaseCoroutinePresenter {
var presenterScope = CoroutineScope(Job() + Dispatchers.Default)
open fun onCreate() {
presenterScope = CoroutineScope(Job() + Dispatchers.Default)
}
open fun onDestroy() {
presenterScope.cancel()
}
}

View File

@ -12,14 +12,13 @@ import eu.kanade.tachiyomi.extension.model.InstallStep
import eu.kanade.tachiyomi.source.LocalSource import eu.kanade.tachiyomi.source.LocalSource
import eu.kanade.tachiyomi.source.Source import eu.kanade.tachiyomi.source.Source
import eu.kanade.tachiyomi.source.SourceManager import eu.kanade.tachiyomi.source.SourceManager
import eu.kanade.tachiyomi.ui.base.presenter.BaseCoroutinePresenter
import eu.kanade.tachiyomi.ui.migration.MangaItem import eu.kanade.tachiyomi.ui.migration.MangaItem
import eu.kanade.tachiyomi.ui.migration.SelectionHeader import eu.kanade.tachiyomi.ui.migration.SelectionHeader
import eu.kanade.tachiyomi.ui.migration.SourceItem import eu.kanade.tachiyomi.ui.migration.SourceItem
import eu.kanade.tachiyomi.util.system.LocaleHelper import eu.kanade.tachiyomi.util.system.LocaleHelper
import eu.kanade.tachiyomi.util.system.executeOnIO import eu.kanade.tachiyomi.util.system.executeOnIO
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.async import kotlinx.coroutines.async
import kotlinx.coroutines.awaitAll import kotlinx.coroutines.awaitAll
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@ -38,8 +37,7 @@ class ExtensionBottomPresenter(
private val bottomSheet: ExtensionBottomSheet, private val bottomSheet: ExtensionBottomSheet,
private val extensionManager: ExtensionManager = Injekt.get(), private val extensionManager: ExtensionManager = Injekt.get(),
private val preferences: PreferencesHelper = Injekt.get() private val preferences: PreferencesHelper = Injekt.get()
) : ExtensionsChangedListener { ) : BaseCoroutinePresenter(), ExtensionsChangedListener {
private var scope = CoroutineScope(Job() + Dispatchers.Default)
private var extensions = emptyList<ExtensionItem>() private var extensions = emptyList<ExtensionItem>()
@ -56,8 +54,9 @@ class ExtensionBottomPresenter(
private var selectedSource: Long? = null private var selectedSource: Long? = null
private val db: DatabaseHelper = Injekt.get() private val db: DatabaseHelper = Injekt.get()
fun onCreate() { override fun onCreate() {
scope.launch { super.onCreate()
presenterScope.launch {
val extensionJob = async { val extensionJob = async {
extensionManager.findAvailableExtensionsAsync() extensionManager.findAvailableExtensionsAsync()
extensions = toItems( extensions = toItems(
@ -102,12 +101,13 @@ class ExtensionBottomPresenter(
return library.filter { it.source == sourceId }.map(::MangaItem) return library.filter { it.source == sourceId }.map(::MangaItem)
} }
fun onDestroy() { override fun onDestroy() {
super.onDestroy()
extensionManager.removeListener(this) extensionManager.removeListener(this)
} }
fun refreshExtensions() { fun refreshExtensions() {
scope.launch { presenterScope.launch {
extensions = toItems( extensions = toItems(
Triple( Triple(
extensionManager.installedExtensions, extensionManager.installedExtensions,
@ -120,7 +120,7 @@ class ExtensionBottomPresenter(
} }
fun refreshMigrations() { fun refreshMigrations() {
scope.launch { presenterScope.launch {
val favs = db.getFavoriteMangas().executeOnIO() val favs = db.getFavoriteMangas().executeOnIO()
sourceItems = findSourcesWithManga(favs) sourceItems = findSourcesWithManga(favs)
mangaItems = HashMap( mangaItems = HashMap(
@ -241,14 +241,14 @@ class ExtensionBottomPresenter(
fun setSelectedSource(source: Source) { fun setSelectedSource(source: Source) {
selectedSource = source.id selectedSource = source.id
scope.launch { presenterScope.launch {
withContext(Dispatchers.Main) { bottomSheet.setMigrationManga(mangaItems[source.id]) } withContext(Dispatchers.Main) { bottomSheet.setMigrationManga(mangaItems[source.id]) }
} }
} }
fun deselectSource() { fun deselectSource() {
selectedSource = null selectedSource = null
scope.launch { presenterScope.launch {
withContext(Dispatchers.Main) { bottomSheet.setMigrationSources(sourceItems) } withContext(Dispatchers.Main) { bottomSheet.setMigrationSources(sourceItems) }
} }
} }

View File

@ -29,7 +29,7 @@ import eu.kanade.tachiyomi.data.download.DownloadService
import eu.kanade.tachiyomi.data.download.model.Download import eu.kanade.tachiyomi.data.download.model.Download
import eu.kanade.tachiyomi.data.library.LibraryUpdateService import eu.kanade.tachiyomi.data.library.LibraryUpdateService
import eu.kanade.tachiyomi.databinding.RecentsControllerBinding import eu.kanade.tachiyomi.databinding.RecentsControllerBinding
import eu.kanade.tachiyomi.ui.base.controller.BaseController import eu.kanade.tachiyomi.ui.base.controller.BaseCoroutineController
import eu.kanade.tachiyomi.ui.base.controller.DialogController import eu.kanade.tachiyomi.ui.base.controller.DialogController
import eu.kanade.tachiyomi.ui.main.BottomSheetController import eu.kanade.tachiyomi.ui.main.BottomSheetController
import eu.kanade.tachiyomi.ui.main.FloatingSearchInterface import eu.kanade.tachiyomi.ui.main.FloatingSearchInterface
@ -65,7 +65,7 @@ import kotlin.math.min
* UI related actions should be called from here. * UI related actions should be called from here.
*/ */
class RecentsController(bundle: Bundle? = null) : class RecentsController(bundle: Bundle? = null) :
BaseController<RecentsControllerBinding>(bundle), BaseCoroutineController<RecentsControllerBinding, RecentsPresenter>(bundle),
RecentMangaAdapter.RecentsInterface, RecentMangaAdapter.RecentsInterface,
FlexibleAdapter.OnItemClickListener, FlexibleAdapter.OnItemClickListener,
FlexibleAdapter.OnItemLongClickListener, FlexibleAdapter.OnItemLongClickListener,
@ -92,7 +92,7 @@ class RecentsController(bundle: Bundle? = null) :
var displaySheet: TabbedRecentsOptionsSheet? = null var displaySheet: TabbedRecentsOptionsSheet? = null
private var progressItem: ProgressItem? = null private var progressItem: ProgressItem? = null
private var presenter = RecentsPresenter(this) override var presenter = RecentsPresenter(this)
private var snack: Snackbar? = null private var snack: Snackbar? = null
private var lastChapterId: Long? = null private var lastChapterId: Long? = null
private var showingDownloads = false private var showingDownloads = false
@ -192,8 +192,6 @@ class RecentsController(bundle: Bundle? = null) :
binding.fakeAppBar.alpha = if (isExpanded) 1f else 0f binding.fakeAppBar.alpha = if (isExpanded) 1f else 0f
} }
presenter.onCreate()
if (presenter.recentItems.isNotEmpty()) { if (presenter.recentItems.isNotEmpty()) {
adapter.updateDataSet(presenter.recentItems) adapter.updateDataSet(presenter.recentItems)
} else { } else {
@ -375,7 +373,6 @@ class RecentsController(bundle: Bundle? = null) :
override fun onDestroy() { override fun onDestroy() {
super.onDestroy() super.onDestroy()
snack?.dismiss() snack?.dismiss()
presenter.onDestroy()
snack = null snack = null
} }
@ -383,7 +380,6 @@ class RecentsController(bundle: Bundle? = null) :
super.onDestroyView(view) super.onDestroyView(view)
displaySheet?.dismiss() displaySheet?.dismiss()
displaySheet = null displaySheet = null
presenter.cancelScope()
} }
fun refresh() = presenter.getRecents() fun refresh() = presenter.getRecents()

View File

@ -13,8 +13,9 @@ 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.source.SourceManager import eu.kanade.tachiyomi.source.SourceManager
import eu.kanade.tachiyomi.ui.base.presenter.BaseCoroutinePresenter
import eu.kanade.tachiyomi.util.system.executeOnIO import eu.kanade.tachiyomi.util.system.executeOnIO
import kotlinx.coroutines.CoroutineScope import eu.kanade.tachiyomi.util.system.launchUI
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job import kotlinx.coroutines.Job
import kotlinx.coroutines.cancel import kotlinx.coroutines.cancel
@ -36,9 +37,7 @@ class RecentsPresenter(
val preferences: PreferencesHelper = Injekt.get(), val preferences: PreferencesHelper = Injekt.get(),
val downloadManager: DownloadManager = Injekt.get(), val downloadManager: DownloadManager = Injekt.get(),
private val db: DatabaseHelper = Injekt.get() private val db: DatabaseHelper = Injekt.get()
) : DownloadQueue.DownloadListener, LibraryServiceListener { ) : BaseCoroutinePresenter(), DownloadQueue.DownloadListener, LibraryServiceListener {
private var scope = CoroutineScope(Job() + Dispatchers.Default)
private var recentsJob: Job? = null private var recentsJob: Job? = null
var recentItems = listOf<RecentMangaItem>() var recentItems = listOf<RecentMangaItem>()
@ -73,7 +72,8 @@ class RecentsPresenter(
private val isOnFirstPage: Boolean private val isOnFirstPage: Boolean
get() = pageOffset == 0 get() = pageOffset == 0
fun onCreate() { override fun onCreate() {
super.onCreate()
downloadManager.addListener(this) downloadManager.addListener(this)
LibraryUpdateService.setListener(this) LibraryUpdateService.setListener(this)
if (lastRecents != null) { if (lastRecents != null) {
@ -83,7 +83,6 @@ class RecentsPresenter(
lastRecents = null lastRecents = null
} }
getRecents() getRecents()
scope = CoroutineScope(Job() + Dispatchers.Default)
listOf( listOf(
preferences.groupChaptersHistory(), preferences.groupChaptersHistory(),
preferences.showReadInAllRecents(), preferences.showReadInAllRecents(),
@ -95,14 +94,14 @@ class RecentsPresenter(
resetOffsets() resetOffsets()
getRecents() getRecents()
} }
.launchIn(scope) .launchIn(presenterScope)
} }
} }
fun getRecents(updatePageCount: Boolean = false) { fun getRecents(updatePageCount: Boolean = false) {
val oldQuery = query val oldQuery = query
recentsJob?.cancel() recentsJob?.cancel()
recentsJob = scope.launch { recentsJob = presenterScope.launch {
runRecents(oldQuery, updatePageCount) runRecents(oldQuery, updatePageCount)
} }
} }
@ -324,16 +323,13 @@ class RecentsPresenter(
} }
} }
fun onDestroy() { override fun onDestroy() {
super.onDestroy()
downloadManager.removeListener(this) downloadManager.removeListener(this)
LibraryUpdateService.removeListener(this) LibraryUpdateService.removeListener(this)
lastRecents = recentItems lastRecents = recentItems
} }
fun cancelScope() {
scope.cancel()
}
fun toggleGroupRecents(pref: Int, updatePref: Boolean = true) { fun toggleGroupRecents(pref: Int, updatePref: Boolean = true) {
if (updatePref) { if (updatePref) {
preferences.recentsViewType().set(pref) preferences.recentsViewType().set(pref)
@ -361,13 +357,11 @@ class RecentsPresenter(
override fun updateDownload(download: Download) { override fun updateDownload(download: Download) {
recentItems.find { it.chapter.id == download.chapter.id }?.download = download recentItems.find { it.chapter.id == download.chapter.id }?.download = download
scope.launch(Dispatchers.Main) { presenterScope.launchUI { controller?.updateChapterDownload(download) }
controller?.updateChapterDownload(download)
}
} }
override fun updateDownloads() { override fun updateDownloads() {
scope.launch { presenterScope.launch {
setDownloadedChapters(recentItems) setDownloadedChapters(recentItems)
withContext(Dispatchers.Main) { withContext(Dispatchers.Main) {
controller?.showLists(recentItems, true) controller?.showLists(recentItems, true)
@ -377,9 +371,9 @@ class RecentsPresenter(
override fun onUpdateManga(manga: Manga?) { override fun onUpdateManga(manga: Manga?) {
if (manga == null && !LibraryUpdateService.isRunning()) { if (manga == null && !LibraryUpdateService.isRunning()) {
scope.launch(Dispatchers.Main) { controller?.setRefreshing(false) } presenterScope.launchUI { controller?.setRefreshing(false) }
} else if (manga == null) { } else if (manga == null) {
scope.launch(Dispatchers.Main) { controller?.setRefreshing(true) } presenterScope.launchUI { controller?.setRefreshing(true) }
} else { } else {
getRecents() getRecents()
} }
@ -443,7 +437,7 @@ class RecentsPresenter(
lastRead: Int? = null, lastRead: Int? = null,
pagesLeft: Int? = null pagesLeft: Int? = null
) { ) {
scope.launch(Dispatchers.IO) { presenterScope.launch(Dispatchers.IO) {
chapter.apply { chapter.apply {
this.read = read this.read = read
if (!read) { if (!read) {