mirror of
https://github.com/null2264/yokai.git
synced 2025-06-21 10:44:42 +00:00
Use generics with BaseCoroutinePresenter
Which has helped the app not run out of memory and crash 🥳 try as i might it's fairly stable now
Too anyone reading this. I'm very happy, I didn't even make these changes for memory management
This commit is contained in:
parent
3cabd7f6f5
commit
9f4a6698be
9 changed files with 54 additions and 44 deletions
|
@ -5,15 +5,19 @@ 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) :
|
||||
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.takeView(this)
|
||||
presenter.onCreate()
|
||||
}
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
private fun <View> BaseCoroutinePresenter<View>.takeView(view: Any) = attachView(view as? View)
|
||||
|
||||
override fun onDestroyView(view: View) {
|
||||
super.onDestroyView(view)
|
||||
presenter.onDestroy()
|
||||
|
|
|
@ -5,8 +5,18 @@ import kotlinx.coroutines.Dispatchers
|
|||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.cancel
|
||||
|
||||
open class BaseCoroutinePresenter {
|
||||
open class BaseCoroutinePresenter<T> {
|
||||
lateinit var presenterScope: CoroutineScope
|
||||
protected var controller: T? = null
|
||||
|
||||
/**
|
||||
* Attaches a view to the presenter.
|
||||
*
|
||||
* @param view a view to attach.
|
||||
*/
|
||||
open fun attachView(view: T?) {
|
||||
controller = view
|
||||
}
|
||||
|
||||
open fun onCreate() {
|
||||
presenterScope = CoroutineScope(Job() + Dispatchers.Default)
|
||||
|
@ -14,5 +24,6 @@ open class BaseCoroutinePresenter {
|
|||
|
||||
open fun onDestroy() {
|
||||
presenterScope.cancel()
|
||||
controller = null
|
||||
}
|
||||
}
|
||||
|
|
|
@ -40,10 +40,9 @@ typealias ExtensionIntallInfo = Pair<InstallStep, PackageInstaller.SessionInfo?>
|
|||
* Presenter of [ExtensionBottomSheet].
|
||||
*/
|
||||
class ExtensionBottomPresenter(
|
||||
private val bottomSheet: ExtensionBottomSheet,
|
||||
private val extensionManager: ExtensionManager = Injekt.get(),
|
||||
val preferences: PreferencesHelper = Injekt.get()
|
||||
) : BaseCoroutinePresenter() {
|
||||
) : BaseCoroutinePresenter<ExtensionBottomSheet>() {
|
||||
|
||||
private var extensions = emptyList<ExtensionItem>()
|
||||
|
||||
|
@ -73,7 +72,7 @@ class ExtensionBottomPresenter(
|
|||
extensionManager.availableExtensions
|
||||
)
|
||||
)
|
||||
withContext(Dispatchers.Main) { bottomSheet.setExtensions(extensions, false) }
|
||||
withContext(Dispatchers.Main) { controller?.setExtensions(extensions, false) }
|
||||
}
|
||||
val migrationJob = async {
|
||||
val favs = db.getFavoriteMangas().executeOnIO()
|
||||
|
@ -88,9 +87,9 @@ class ExtensionBottomPresenter(
|
|||
)
|
||||
withContext(Dispatchers.Main) {
|
||||
if (selectedSource != null) {
|
||||
bottomSheet.setMigrationManga(mangaItems[selectedSource])
|
||||
controller?.setMigrationManga(mangaItems[selectedSource])
|
||||
} else {
|
||||
bottomSheet.setMigrationSources(sourceItems)
|
||||
controller?.setMigrationSources(sourceItems)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -110,7 +109,7 @@ class ExtensionBottomPresenter(
|
|||
extensionManager.availableExtensions
|
||||
)
|
||||
)
|
||||
withUIContext { bottomSheet.setExtensions(extensions) }
|
||||
withUIContext { controller?.setExtensions(extensions) }
|
||||
return@collect
|
||||
}
|
||||
val extension = extensions.find { item ->
|
||||
|
@ -126,7 +125,7 @@ class ExtensionBottomPresenter(
|
|||
}
|
||||
val item = updateInstallStep(extension.extension, it.second.first, it.second.second)
|
||||
if (item != null) {
|
||||
withUIContext { bottomSheet.downloadUpdate(item) }
|
||||
withUIContext { controller?.downloadUpdate(item) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -153,7 +152,7 @@ class ExtensionBottomPresenter(
|
|||
extensionManager.availableExtensions
|
||||
)
|
||||
)
|
||||
withContext(Dispatchers.Main) { bottomSheet.setExtensions(extensions, false) }
|
||||
withContext(Dispatchers.Main) { controller?.setExtensions(extensions, false) }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -168,9 +167,9 @@ class ExtensionBottomPresenter(
|
|||
)
|
||||
withContext(Dispatchers.Main) {
|
||||
if (selectedSource != null) {
|
||||
bottomSheet.setMigrationManga(mangaItems[selectedSource])
|
||||
controller?.setMigrationManga(mangaItems[selectedSource])
|
||||
} else {
|
||||
bottomSheet.setMigrationSources(sourceItems)
|
||||
controller?.setMigrationSources(sourceItems)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -178,7 +177,7 @@ class ExtensionBottomPresenter(
|
|||
|
||||
@Synchronized
|
||||
private fun toItems(tuple: ExtensionTuple): List<ExtensionItem> {
|
||||
val context = bottomSheet.context
|
||||
val context = controller?.context ?: return emptyList()
|
||||
val activeLangs = preferences.enabledLanguages().get()
|
||||
val showNsfwSources = preferences.showNsfwSources().get()
|
||||
|
||||
|
@ -266,7 +265,7 @@ class ExtensionBottomPresenter(
|
|||
}
|
||||
|
||||
private fun extensionInstallDate(pkgName: String): Long {
|
||||
val context = bottomSheet.context
|
||||
val context = controller?.context ?: return 0
|
||||
return try {
|
||||
context.packageManager.getPackageInfo(pkgName, 0).firstInstallTime
|
||||
} catch (e: java.lang.Exception) {
|
||||
|
@ -275,7 +274,7 @@ class ExtensionBottomPresenter(
|
|||
}
|
||||
|
||||
private fun extensionUpdateDate(pkgName: String): Long {
|
||||
val context = bottomSheet.context
|
||||
val context = controller?.context ?: return 0
|
||||
return try {
|
||||
context.packageManager.getPackageInfo(pkgName, 0).lastUpdateTime
|
||||
} catch (e: java.lang.Exception) {
|
||||
|
@ -331,15 +330,15 @@ class ExtensionBottomPresenter(
|
|||
|
||||
fun updateExtensions(extensions: List<Extension.Installed>) {
|
||||
if (extensions.isEmpty()) return
|
||||
val context = bottomSheet.context
|
||||
val context = controller?.context ?: return
|
||||
extensions.forEach {
|
||||
val pkgName = it.pkgName
|
||||
currentDownloads[pkgName] = InstallStep.Pending to null
|
||||
val item = updateInstallStep(it, InstallStep.Pending, null) ?: return@forEach
|
||||
bottomSheet.downloadUpdate(item)
|
||||
controller?.downloadUpdate(item)
|
||||
}
|
||||
val intent = ExtensionInstallService.jobIntent(
|
||||
bottomSheet.context,
|
||||
context,
|
||||
extensions.mapNotNull { extension ->
|
||||
extensionManager.availableExtensions.find { it.pkgName == extension.pkgName }
|
||||
}
|
||||
|
@ -362,14 +361,14 @@ class ExtensionBottomPresenter(
|
|||
fun setSelectedSource(source: Source) {
|
||||
selectedSource = source.id
|
||||
presenterScope.launch {
|
||||
withContext(Dispatchers.Main) { bottomSheet.setMigrationManga(mangaItems[source.id]) }
|
||||
withContext(Dispatchers.Main) { controller?.setMigrationManga(mangaItems[source.id]) }
|
||||
}
|
||||
}
|
||||
|
||||
fun deselectSource() {
|
||||
selectedSource = null
|
||||
presenterScope.launch {
|
||||
withContext(Dispatchers.Main) { bottomSheet.setMigrationSources(sourceItems) }
|
||||
withContext(Dispatchers.Main) { controller?.setMigrationSources(sourceItems) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -61,7 +61,7 @@ class ExtensionBottomSheet @JvmOverloads constructor(context: Context, attrs: At
|
|||
val adapters
|
||||
get() = listOf(extAdapter, migAdapter)
|
||||
|
||||
val presenter = ExtensionBottomPresenter(this)
|
||||
val presenter = ExtensionBottomPresenter()
|
||||
|
||||
private var extensions: List<ExtensionItem> = emptyList()
|
||||
var canExpand = false
|
||||
|
@ -84,6 +84,7 @@ class ExtensionBottomSheet @JvmOverloads constructor(context: Context, attrs: At
|
|||
|
||||
fun onCreate(controller: BrowseController) {
|
||||
// Initialize adapter, scroll listener and recycler views
|
||||
presenter.attachView(this)
|
||||
extAdapter = ExtensionAdapter(this)
|
||||
extAdapter?.stateRestorationPolicy = RecyclerView.Adapter.StateRestorationPolicy.PREVENT_WHEN_EMPTY
|
||||
if (migAdapter == null) {
|
||||
|
@ -386,6 +387,13 @@ class ExtensionBottomSheet @JvmOverloads constructor(context: Context, attrs: At
|
|||
presenter.uninstallExtension(pkgName)
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the view of this adapter is being destroyed.
|
||||
*/
|
||||
fun onDestroy() {
|
||||
presenter.onDestroy()
|
||||
}
|
||||
|
||||
private inner class TabbedSheetAdapter : RecyclerViewPagerAdapter() {
|
||||
|
||||
override fun getCount(): Int {
|
||||
|
@ -451,16 +459,5 @@ class ExtensionBottomSheet @JvmOverloads constructor(context: Context, attrs: At
|
|||
val index = adapters.indexOfFirst { it == view.binding?.recycler?.adapter }
|
||||
return if (index == -1) POSITION_NONE else index
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the view of this adapter is being destroyed.
|
||||
*/
|
||||
fun onDestroy() {
|
||||
/*for (view in boundViews) {
|
||||
if (view is LibraryCategoryView) {
|
||||
view.onDestroy()
|
||||
}
|
||||
}*/
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -176,7 +176,7 @@ class LibraryController(
|
|||
private var lastItemPosition: Int? = null
|
||||
private var lastItem: IFlexible<*>? = null
|
||||
|
||||
override var presenter = LibraryPresenter(this)
|
||||
override var presenter = LibraryPresenter()
|
||||
|
||||
private var observeLater: Boolean = false
|
||||
var searchItem = SearchGlobalItem()
|
||||
|
|
|
@ -56,14 +56,13 @@ import kotlin.random.Random
|
|||
* Presenter of [LibraryController].
|
||||
*/
|
||||
class LibraryPresenter(
|
||||
private val view: LibraryController,
|
||||
val db: DatabaseHelper = Injekt.get(),
|
||||
private val preferences: PreferencesHelper = Injekt.get(),
|
||||
private val coverCache: CoverCache = Injekt.get(),
|
||||
val sourceManager: SourceManager = Injekt.get(),
|
||||
private val downloadManager: DownloadManager = Injekt.get(),
|
||||
private val chapterFilter: ChapterFilter = Injekt.get()
|
||||
) : BaseCoroutinePresenter() {
|
||||
) : BaseCoroutinePresenter<LibraryController>() {
|
||||
|
||||
private val context = preferences.context
|
||||
|
||||
|
@ -133,7 +132,7 @@ class LibraryPresenter(
|
|||
// Doing this instead of a job in case the app isn't used often
|
||||
presenterScope.launchIO {
|
||||
setSearchSuggestion(preferences, db, sourceManager)
|
||||
withUIContext { view.setTitle() }
|
||||
withUIContext { controller?.setTitle() }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -184,7 +183,7 @@ class LibraryPresenter(
|
|||
preferences.lastUsedCategory().set(order)
|
||||
val category = categories.find { it.order == order }?.id ?: return
|
||||
currentCategory = category
|
||||
view.onNextLibraryUpdate(
|
||||
controller?.onNextLibraryUpdate(
|
||||
sectionedLibraryItems[currentCategory] ?: blankItem()
|
||||
)
|
||||
}
|
||||
|
@ -205,7 +204,7 @@ class LibraryPresenter(
|
|||
if (!show && currentCategory == -1) currentCategory = categories.find {
|
||||
it.order == preferences.lastUsedCategory().get()
|
||||
}?.id ?: 0
|
||||
view.onNextLibraryUpdate(
|
||||
controller?.onNextLibraryUpdate(
|
||||
if (!show) sectionedLibraryItems[currentCategory]
|
||||
?: sectionedLibraryItems[categories.first().id] ?: blankItem()
|
||||
else libraryItems,
|
||||
|
@ -227,7 +226,7 @@ class LibraryPresenter(
|
|||
it.order == preferences.lastUsedCategory().get()
|
||||
}?.id ?: 0
|
||||
withUIContext {
|
||||
view.onNextLibraryUpdate(
|
||||
controller?.onNextLibraryUpdate(
|
||||
if (!showAll) sectionedLibraryItems[currentCategory]
|
||||
?: sectionedLibraryItems[categories.first().id] ?: blankItem()
|
||||
else libraryItems,
|
||||
|
@ -763,7 +762,7 @@ class LibraryPresenter(
|
|||
|
||||
/** Create a default category with the sort set */
|
||||
private fun createDefaultCategory(): Category {
|
||||
val default = Category.createDefault(view.applicationContext ?: context)
|
||||
val default = Category.createDefault(controller?.applicationContext ?: context)
|
||||
default.order = -1
|
||||
val defOrder = preferences.defaultMangaOrder().get()
|
||||
if (defOrder.firstOrNull()?.isLetter() == true) default.mangaSort = defOrder.first()
|
||||
|
|
|
@ -111,7 +111,7 @@ class RecentsController(bundle: Bundle? = null) :
|
|||
var displaySheet: TabbedRecentsOptionsSheet? = null
|
||||
|
||||
private var progressItem: ProgressItem? = null
|
||||
override var presenter = RecentsPresenter(this)
|
||||
override var presenter = RecentsPresenter()
|
||||
private var snack: Snackbar? = null
|
||||
private var lastChapterId: Long? = null
|
||||
private var showingDownloads = false
|
||||
|
|
|
@ -38,12 +38,11 @@ import java.util.concurrent.TimeUnit
|
|||
import kotlin.math.abs
|
||||
|
||||
class RecentsPresenter(
|
||||
val controller: RecentsController?,
|
||||
val preferences: PreferencesHelper = Injekt.get(),
|
||||
val downloadManager: DownloadManager = Injekt.get(),
|
||||
private val db: DatabaseHelper = Injekt.get(),
|
||||
private val chapterFilter: ChapterFilter = Injekt.get()
|
||||
) : BaseCoroutinePresenter(), DownloadQueue.DownloadListener, LibraryServiceListener, DownloadServiceListener {
|
||||
) : BaseCoroutinePresenter<RecentsController>(), DownloadQueue.DownloadListener, LibraryServiceListener, DownloadServiceListener {
|
||||
|
||||
private var recentsJob: Job? = null
|
||||
var recentItems = listOf<RecentMangaItem>()
|
||||
|
@ -518,7 +517,7 @@ class RecentsPresenter(
|
|||
private set
|
||||
|
||||
suspend fun getRecentManga(includeRead: Boolean = false): List<Pair<Manga, Long>> {
|
||||
val presenter = RecentsPresenter(null)
|
||||
val presenter = RecentsPresenter()
|
||||
presenter.viewType = 1
|
||||
SHORT_LIMIT = if (includeRead) 50 else 25
|
||||
presenter.runRecents(limit = true, includeReadAnyway = includeRead)
|
||||
|
|
|
@ -419,6 +419,7 @@ class BrowseController :
|
|||
|
||||
override fun onDestroyView(view: View) {
|
||||
adapter = null
|
||||
binding.bottomSheet.root.onDestroy()
|
||||
super.onDestroyView(view)
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue