Change PageLoader lifecycle

pull/311/head
Koitharu 3 years ago
parent 8294eb4ecd
commit b4e0704a3a
No known key found for this signature in database
GPG Key ID: 8E861F8CE6E7CE27

@ -23,6 +23,7 @@ import org.koitharu.kotatsu.core.prefs.AppSettings
import org.koitharu.kotatsu.local.data.PagesCache import org.koitharu.kotatsu.local.data.PagesCache
import org.koitharu.kotatsu.local.domain.LocalMangaRepository import org.koitharu.kotatsu.local.domain.LocalMangaRepository
import org.koitharu.kotatsu.parsers.MangaLoaderContext import org.koitharu.kotatsu.parsers.MangaLoaderContext
import org.koitharu.kotatsu.reader.domain.PageLoader
import org.koitharu.kotatsu.utils.ext.processLifecycleScope import org.koitharu.kotatsu.utils.ext.processLifecycleScope
import javax.inject.Inject import javax.inject.Inject
@ -125,6 +126,7 @@ class KotatsuApp : Application(), Configuration.Provider {
.setClassInstanceLimit(LocalMangaRepository::class.java, 1) .setClassInstanceLimit(LocalMangaRepository::class.java, 1)
.setClassInstanceLimit(PagesCache::class.java, 1) .setClassInstanceLimit(PagesCache::class.java, 1)
.setClassInstanceLimit(MangaLoaderContext::class.java, 1) .setClassInstanceLimit(MangaLoaderContext::class.java, 1)
.setClassInstanceLimit(PageLoader::class.java, 1)
.penaltyLog() .penaltyLog()
.build(), .build(),
) )

@ -5,6 +5,9 @@ import android.graphics.BitmapFactory
import android.net.Uri import android.net.Uri
import androidx.collection.LongSparseArray import androidx.collection.LongSparseArray
import androidx.collection.set import androidx.collection.set
import dagger.hilt.android.ActivityRetainedLifecycle
import dagger.hilt.android.lifecycle.RetainedLifecycle
import dagger.hilt.android.scopes.ActivityRetainedScoped
import kotlinx.coroutines.CoroutineExceptionHandler import kotlinx.coroutines.CoroutineExceptionHandler
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
@ -18,7 +21,6 @@ import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock import kotlinx.coroutines.sync.withLock
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
import okhttp3.Request import okhttp3.Request
import okio.Closeable
import org.koitharu.kotatsu.core.network.CommonHeaders import org.koitharu.kotatsu.core.network.CommonHeaders
import org.koitharu.kotatsu.core.parser.MangaRepository import org.koitharu.kotatsu.core.parser.MangaRepository
import org.koitharu.kotatsu.core.parser.RemoteMangaRepository import org.koitharu.kotatsu.core.parser.RemoteMangaRepository
@ -42,12 +44,18 @@ import kotlin.coroutines.CoroutineContext
private const val PROGRESS_UNDEFINED = -1f private const val PROGRESS_UNDEFINED = -1f
private const val PREFETCH_LIMIT_DEFAULT = 10 private const val PREFETCH_LIMIT_DEFAULT = 10
@ActivityRetainedScoped
class PageLoader @Inject constructor( class PageLoader @Inject constructor(
lifecycle: ActivityRetainedLifecycle,
private val okHttp: OkHttpClient, private val okHttp: OkHttpClient,
private val cache: PagesCache, private val cache: PagesCache,
private val settings: AppSettings, private val settings: AppSettings,
private val mangaRepositoryFactory: MangaRepository.Factory, private val mangaRepositoryFactory: MangaRepository.Factory,
) : Closeable { ) : RetainedLifecycle.OnClearedListener {
init {
lifecycle.addOnClearedListener(this)
}
val loaderScope = CoroutineScope(SupervisorJob() + InternalErrorHandler() + Dispatchers.Default) val loaderScope = CoroutineScope(SupervisorJob() + InternalErrorHandler() + Dispatchers.Default)
@ -59,7 +67,7 @@ class PageLoader @Inject constructor(
private val counter = AtomicInteger(0) private val counter = AtomicInteger(0)
private var prefetchQueueLimit = PREFETCH_LIMIT_DEFAULT // TODO adaptive private var prefetchQueueLimit = PREFETCH_LIMIT_DEFAULT // TODO adaptive
override fun close() { override fun onCleared() {
loaderScope.cancel() loaderScope.cancel()
synchronized(tasks) { synchronized(tasks) {
tasks.clear() tasks.clear()

@ -56,7 +56,6 @@ import org.koitharu.kotatsu.utils.ext.requireValue
import org.koitharu.kotatsu.utils.ext.runCatchingCancellable import org.koitharu.kotatsu.utils.ext.runCatchingCancellable
import java.util.Date import java.util.Date
import javax.inject.Inject import javax.inject.Inject
import javax.inject.Provider
private const val BOUNDS_PAGE_OFFSET = 2 private const val BOUNDS_PAGE_OFFSET = 2
private const val PREFETCH_LIMIT = 10 private const val PREFETCH_LIMIT = 10
@ -70,7 +69,7 @@ class ReaderViewModel @Inject constructor(
private val bookmarksRepository: BookmarksRepository, private val bookmarksRepository: BookmarksRepository,
private val settings: AppSettings, private val settings: AppSettings,
private val pageSaveHelper: PageSaveHelper, private val pageSaveHelper: PageSaveHelper,
pageLoaderFactory: Provider<PageLoader>, private val pageLoader: PageLoader,
) : BaseViewModel() { ) : BaseViewModel() {
private val intent = MangaIntent(savedStateHandle) private val intent = MangaIntent(savedStateHandle)
@ -84,7 +83,6 @@ class ReaderViewModel @Inject constructor(
private val chapters: LongSparseArray<MangaChapter> private val chapters: LongSparseArray<MangaChapter>
get() = chaptersLoader.chapters get() = chaptersLoader.chapters
val pageLoader = pageLoaderFactory.get()
private val chaptersLoader = ChaptersLoader(mangaRepositoryFactory) private val chaptersLoader = ChaptersLoader(mangaRepositoryFactory)
val readerMode = MutableLiveData<ReaderMode>() val readerMode = MutableLiveData<ReaderMode>()
@ -148,10 +146,10 @@ class ReaderViewModel @Inject constructor(
}.launchIn(viewModelScope) }.launchIn(viewModelScope)
} }
override fun onCleared() { /*override fun onCleared() {
pageLoader.close() pageLoader.close()
super.onCleared() super.onCleared()
} }*/
fun reload() { fun reload() {
loadingJob?.cancel() loadingJob?.cancel()

@ -10,6 +10,7 @@ import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.async import kotlinx.coroutines.async
import org.koitharu.kotatsu.core.os.NetworkState import org.koitharu.kotatsu.core.os.NetworkState
import org.koitharu.kotatsu.databinding.FragmentReaderStandardBinding import org.koitharu.kotatsu.databinding.FragmentReaderStandardBinding
import org.koitharu.kotatsu.reader.domain.PageLoader
import org.koitharu.kotatsu.reader.ui.ReaderState import org.koitharu.kotatsu.reader.ui.ReaderState
import org.koitharu.kotatsu.reader.ui.pager.BaseReader import org.koitharu.kotatsu.reader.ui.pager.BaseReader
import org.koitharu.kotatsu.reader.ui.pager.BaseReaderAdapter import org.koitharu.kotatsu.reader.ui.pager.BaseReaderAdapter
@ -28,6 +29,9 @@ class ReversedReaderFragment : BaseReader<FragmentReaderStandardBinding>() {
@Inject @Inject
lateinit var networkState: NetworkState lateinit var networkState: NetworkState
@Inject
lateinit var pageLoader: PageLoader
private var pagerAdapter: ReversedPagesAdapter? = null private var pagerAdapter: ReversedPagesAdapter? = null
override fun onInflateView( override fun onInflateView(
@ -40,7 +44,7 @@ class ReversedReaderFragment : BaseReader<FragmentReaderStandardBinding>() {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
pagerAdapter = ReversedPagesAdapter( pagerAdapter = ReversedPagesAdapter(
lifecycleOwner = viewLifecycleOwner, lifecycleOwner = viewLifecycleOwner,
loader = viewModel.pageLoader, loader = pageLoader,
settings = viewModel.readerSettings, settings = viewModel.readerSettings,
networkState = networkState, networkState = networkState,
exceptionResolver = exceptionResolver, exceptionResolver = exceptionResolver,

@ -10,6 +10,7 @@ import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.async import kotlinx.coroutines.async
import org.koitharu.kotatsu.core.os.NetworkState import org.koitharu.kotatsu.core.os.NetworkState
import org.koitharu.kotatsu.databinding.FragmentReaderStandardBinding import org.koitharu.kotatsu.databinding.FragmentReaderStandardBinding
import org.koitharu.kotatsu.reader.domain.PageLoader
import org.koitharu.kotatsu.reader.ui.ReaderState import org.koitharu.kotatsu.reader.ui.ReaderState
import org.koitharu.kotatsu.reader.ui.pager.BaseReader import org.koitharu.kotatsu.reader.ui.pager.BaseReader
import org.koitharu.kotatsu.reader.ui.pager.BaseReaderAdapter import org.koitharu.kotatsu.reader.ui.pager.BaseReaderAdapter
@ -27,6 +28,9 @@ class PagerReaderFragment : BaseReader<FragmentReaderStandardBinding>() {
@Inject @Inject
lateinit var networkState: NetworkState lateinit var networkState: NetworkState
@Inject
lateinit var pageLoader: PageLoader
private var pagesAdapter: PagesAdapter? = null private var pagesAdapter: PagesAdapter? = null
override fun onInflateView( override fun onInflateView(
@ -39,7 +43,7 @@ class PagerReaderFragment : BaseReader<FragmentReaderStandardBinding>() {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
pagesAdapter = PagesAdapter( pagesAdapter = PagesAdapter(
lifecycleOwner = viewLifecycleOwner, lifecycleOwner = viewLifecycleOwner,
loader = viewModel.pageLoader, loader = pageLoader,
settings = viewModel.readerSettings, settings = viewModel.readerSettings,
networkState = networkState, networkState = networkState,
exceptionResolver = exceptionResolver, exceptionResolver = exceptionResolver,

@ -9,6 +9,7 @@ import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.async import kotlinx.coroutines.async
import org.koitharu.kotatsu.core.os.NetworkState import org.koitharu.kotatsu.core.os.NetworkState
import org.koitharu.kotatsu.databinding.FragmentReaderWebtoonBinding import org.koitharu.kotatsu.databinding.FragmentReaderWebtoonBinding
import org.koitharu.kotatsu.reader.domain.PageLoader
import org.koitharu.kotatsu.reader.ui.ReaderState import org.koitharu.kotatsu.reader.ui.ReaderState
import org.koitharu.kotatsu.reader.ui.pager.BaseReader import org.koitharu.kotatsu.reader.ui.pager.BaseReader
import org.koitharu.kotatsu.reader.ui.pager.BaseReaderAdapter import org.koitharu.kotatsu.reader.ui.pager.BaseReaderAdapter
@ -24,6 +25,9 @@ class WebtoonReaderFragment : BaseReader<FragmentReaderWebtoonBinding>() {
@Inject @Inject
lateinit var networkState: NetworkState lateinit var networkState: NetworkState
@Inject
lateinit var pageLoader: PageLoader
private val scrollInterpolator = AccelerateDecelerateInterpolator() private val scrollInterpolator = AccelerateDecelerateInterpolator()
private var webtoonAdapter: WebtoonAdapter? = null private var webtoonAdapter: WebtoonAdapter? = null
@ -36,7 +40,7 @@ class WebtoonReaderFragment : BaseReader<FragmentReaderWebtoonBinding>() {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
webtoonAdapter = WebtoonAdapter( webtoonAdapter = WebtoonAdapter(
lifecycleOwner = viewLifecycleOwner, lifecycleOwner = viewLifecycleOwner,
loader = viewModel.pageLoader, loader = pageLoader,
settings = viewModel.readerSettings, settings = viewModel.readerSettings,
networkState = networkState, networkState = networkState,
exceptionResolver = exceptionResolver, exceptionResolver = exceptionResolver,

@ -4,7 +4,6 @@ import android.os.Bundle
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.activity.viewModels
import androidx.fragment.app.FragmentManager import androidx.fragment.app.FragmentManager
import androidx.recyclerview.widget.GridLayoutManager import androidx.recyclerview.widget.GridLayoutManager
import coil.ImageLoader import coil.ImageLoader
@ -21,14 +20,11 @@ import org.koitharu.kotatsu.databinding.SheetPagesBinding
import org.koitharu.kotatsu.list.ui.MangaListSpanResolver import org.koitharu.kotatsu.list.ui.MangaListSpanResolver
import org.koitharu.kotatsu.parsers.model.MangaPage import org.koitharu.kotatsu.parsers.model.MangaPage
import org.koitharu.kotatsu.reader.domain.PageLoader import org.koitharu.kotatsu.reader.domain.PageLoader
import org.koitharu.kotatsu.reader.ui.ReaderActivity
import org.koitharu.kotatsu.reader.ui.ReaderViewModel
import org.koitharu.kotatsu.reader.ui.thumbnails.adapter.PageThumbnailAdapter import org.koitharu.kotatsu.reader.ui.thumbnails.adapter.PageThumbnailAdapter
import org.koitharu.kotatsu.utils.ext.getParcelableCompat import org.koitharu.kotatsu.utils.ext.getParcelableCompat
import org.koitharu.kotatsu.utils.ext.viewLifecycleScope import org.koitharu.kotatsu.utils.ext.viewLifecycleScope
import org.koitharu.kotatsu.utils.ext.withArgs import org.koitharu.kotatsu.utils.ext.withArgs
import javax.inject.Inject import javax.inject.Inject
import javax.inject.Provider
@AndroidEntryPoint @AndroidEntryPoint
class PagesThumbnailsSheet : class PagesThumbnailsSheet :
@ -40,7 +36,7 @@ class PagesThumbnailsSheet :
lateinit var mangaRepositoryFactory: MangaRepository.Factory lateinit var mangaRepositoryFactory: MangaRepository.Factory
@Inject @Inject
lateinit var pageLoaderProvider: Provider<PageLoader> lateinit var pageLoader: PageLoader
@Inject @Inject
lateinit var coil: ImageLoader lateinit var coil: ImageLoader
@ -51,7 +47,6 @@ class PagesThumbnailsSheet :
private lateinit var thumbnails: List<PageThumbnail> private lateinit var thumbnails: List<PageThumbnail>
private var spanResolver: MangaListSpanResolver? = null private var spanResolver: MangaListSpanResolver? = null
private var currentPageIndex = -1 private var currentPageIndex = -1
private var pageLoader: PageLoader? = null
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
@ -79,11 +74,10 @@ class PagesThumbnailsSheet :
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
val title = arguments?.getString(ARG_TITLE)
spanResolver = MangaListSpanResolver(view.resources) spanResolver = MangaListSpanResolver(view.resources)
with(binding.headerBar) { with(binding.headerBar) {
toolbar.title = title title = arguments?.getString(ARG_TITLE)
toolbar.subtitle = null subtitle = null
addOnExpansionChangeListener(this@PagesThumbnailsSheet) addOnExpansionChangeListener(this@PagesThumbnailsSheet)
} }
@ -95,7 +89,7 @@ class PagesThumbnailsSheet :
dataSet = thumbnails, dataSet = thumbnails,
coil = coil, coil = coil,
scope = viewLifecycleScope, scope = viewLifecycleScope,
loader = getPageLoader(), loader = pageLoader,
clickListener = this@PagesThumbnailsSheet, clickListener = this@PagesThumbnailsSheet,
) )
addOnLayoutChangeListener(spanResolver) addOnLayoutChangeListener(spanResolver)
@ -110,8 +104,6 @@ class PagesThumbnailsSheet :
override fun onDestroyView() { override fun onDestroyView() {
super.onDestroyView() super.onDestroyView()
spanResolver = null spanResolver = null
pageLoader?.close()
pageLoader = null
} }
override fun onItemClick(item: MangaPage, view: View) { override fun onItemClick(item: MangaPage, view: View) {
@ -126,21 +118,16 @@ class PagesThumbnailsSheet :
override fun onExpansionStateChanged(headerBar: BottomSheetHeaderBar, isExpanded: Boolean) { override fun onExpansionStateChanged(headerBar: BottomSheetHeaderBar, isExpanded: Boolean) {
if (isExpanded) { if (isExpanded) {
headerBar.toolbar.subtitle = resources.getQuantityString( headerBar.subtitle = resources.getQuantityString(
R.plurals.pages, R.plurals.pages,
thumbnails.size, thumbnails.size,
thumbnails.size, thumbnails.size,
) )
} else { } else {
headerBar.toolbar.subtitle = null headerBar.subtitle = null
} }
} }
private fun getPageLoader(): PageLoader {
val viewModel = (activity as? ReaderActivity)?.viewModels<ReaderViewModel>()?.value
return viewModel?.pageLoader ?: pageLoaderProvider.get().also { pageLoader = it }
}
companion object { companion object {
private const val ARG_PAGES = "pages" private const val ARG_PAGES = "pages"

Loading…
Cancel
Save