Fix MangaDetailsPresenter sharing

This commit is contained in:
Koitharu
2020-06-29 13:06:40 +03:00
parent a2f09d8763
commit 84ef2af82f
14 changed files with 60 additions and 43 deletions

View File

@@ -16,7 +16,7 @@ android {
minSdkVersion 21 minSdkVersion 21
targetSdkVersion 29 targetSdkVersion 29
versionCode gitCommits versionCode gitCommits
versionName '0.5-b1' versionName '0.5-b2'
kapt { kapt {
arguments { arguments {

View File

@@ -29,7 +29,7 @@ class BrowserActivity : BaseActivity(), BrowserCallback {
webView.webViewClient = BrowserClient(this) webView.webViewClient = BrowserClient(this)
val url = intent?.dataString val url = intent?.dataString
if (url.isNullOrEmpty()) { if (url.isNullOrEmpty()) {
finish() finishAfterTransition()
} else { } else {
webView.loadUrl(url) webView.loadUrl(url)
} }
@@ -43,7 +43,7 @@ class BrowserActivity : BaseActivity(), BrowserCallback {
override fun onOptionsItemSelected(item: MenuItem): Boolean = when (item.itemId) { override fun onOptionsItemSelected(item: MenuItem): Boolean = when (item.itemId) {
android.R.id.home -> { android.R.id.home -> {
webView.stopLoading() webView.stopLoading()
finish() finishAfterTransition()
true true
} }
R.id.action_browser -> { R.id.action_browser -> {

View File

@@ -1,12 +1,10 @@
package org.koitharu.kotatsu.ui.common package org.koitharu.kotatsu.ui.common
import android.view.KeyEvent
import android.view.MenuItem import android.view.MenuItem
import android.view.View import android.view.View
import androidx.appcompat.widget.Toolbar import androidx.appcompat.widget.Toolbar
import moxy.MvpAppCompatActivity import moxy.MvpAppCompatActivity
import org.koin.core.KoinComponent import org.koin.core.KoinComponent
import org.koitharu.kotatsu.BuildConfig
import org.koitharu.kotatsu.R import org.koitharu.kotatsu.R
abstract class BaseActivity : MvpAppCompatActivity(), KoinComponent { abstract class BaseActivity : MvpAppCompatActivity(), KoinComponent {
@@ -29,13 +27,4 @@ abstract class BaseActivity : MvpAppCompatActivity(), KoinComponent {
onBackPressed() onBackPressed()
true true
} else super.onOptionsItemSelected(item) } else super.onOptionsItemSelected(item)
override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean {
//TODO remove. Just for testing
if (BuildConfig.DEBUG && keyCode == KeyEvent.KEYCODE_VOLUME_UP) {
recreate()
return true
}
return super.onKeyDown(keyCode, event)
}
} }

View File

@@ -0,0 +1,25 @@
package org.koitharu.kotatsu.ui.common
import android.util.ArrayMap
import moxy.MvpPresenter
import java.lang.ref.WeakReference
abstract class SharedPresenterHolder<T : MvpPresenter<*>> {
private val cache = ArrayMap<Int, WeakReference<T>>(3)
fun getInstance(key: Int): T {
var instance = cache[key]?.get()
if (instance == null) {
instance = onCreatePresenter(key)
cache[key] = WeakReference(instance)
}
return instance
}
fun clear(key: Int) {
cache.remove(key)
}
protected abstract fun onCreatePresenter(key: Int): T
}

View File

@@ -25,7 +25,9 @@ class ChaptersFragment : BaseFragment(R.layout.fragment_chapters), MangaDetailsV
OnRecyclerItemClickListener<MangaChapter>, ActionMode.Callback { OnRecyclerItemClickListener<MangaChapter>, ActionMode.Callback {
@Suppress("unused") @Suppress("unused")
private val presenter by moxyPresenter(factory = MangaDetailsPresenter.Companion::getInstance) private val presenter by moxyPresenter {
MangaDetailsPresenter.getInstance(activity.hashCode())
}
private var manga: Manga? = null private var manga: Manga? = null

View File

@@ -37,7 +37,9 @@ import org.koitharu.kotatsu.utils.ext.getThemeColor
class MangaDetailsActivity : BaseActivity(), MangaDetailsView, class MangaDetailsActivity : BaseActivity(), MangaDetailsView,
TabLayoutMediator.TabConfigurationStrategy { TabLayoutMediator.TabConfigurationStrategy {
private val presenter by moxyPresenter(factory = MangaDetailsPresenter.Companion::getInstance) private val presenter by moxyPresenter {
MangaDetailsPresenter.getInstance(hashCode())
}
private var manga: Manga? = null private var manga: Manga? = null
@@ -52,7 +54,7 @@ class MangaDetailsActivity : BaseActivity(), MangaDetailsView,
presenter.loadDetails(it, true) presenter.loadDetails(it, true)
} ?: intent?.getLongExtra(EXTRA_MANGA_ID, 0)?.takeUnless { it == 0L }?.let { } ?: intent?.getLongExtra(EXTRA_MANGA_ID, 0)?.takeUnless { it == 0L }?.let {
presenter.findMangaById(it) presenter.findMangaById(it)
} ?: finish() } ?: finishAfterTransition()
} }
} }
@@ -73,13 +75,13 @@ class MangaDetailsActivity : BaseActivity(), MangaDetailsView,
this, getString(R.string._s_deleted_from_local_storage, manga.title), this, getString(R.string._s_deleted_from_local_storage, manga.title),
Toast.LENGTH_SHORT Toast.LENGTH_SHORT
).show() ).show()
finish() finishAfterTransition()
} }
override fun onError(e: Throwable) { override fun onError(e: Throwable) {
if (manga == null) { if (manga == null) {
Toast.makeText(this, e.getDisplayMessage(resources), Toast.LENGTH_LONG).show() Toast.makeText(this, e.getDisplayMessage(resources), Toast.LENGTH_LONG).show()
finish() finishAfterTransition()
} else { } else {
Snackbar.make(pager, e.getDisplayMessage(resources), Snackbar.LENGTH_LONG).show() Snackbar.make(pager, e.getDisplayMessage(resources), Snackbar.LENGTH_LONG).show()
} }

View File

@@ -29,7 +29,9 @@ class MangaDetailsFragment : BaseFragment(R.layout.fragment_details), MangaDetai
View.OnLongClickListener { View.OnLongClickListener {
@Suppress("unused") @Suppress("unused")
private val presenter by moxyPresenter(factory = MangaDetailsPresenter.Companion::getInstance) private val presenter by moxyPresenter {
MangaDetailsPresenter.getInstance(activity.hashCode())
}
private var manga: Manga? = null private var manga: Manga? = null
private var history: MangaHistory? = null private var history: MangaHistory? = null

View File

@@ -1,5 +1,6 @@
package org.koitharu.kotatsu.ui.details package org.koitharu.kotatsu.ui.details
import android.util.Log
import kotlinx.coroutines.CancellationException import kotlinx.coroutines.CancellationException
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.* import kotlinx.coroutines.flow.*
@@ -21,13 +22,13 @@ import org.koitharu.kotatsu.domain.history.HistoryRepository
import org.koitharu.kotatsu.domain.history.OnHistoryChangeListener import org.koitharu.kotatsu.domain.history.OnHistoryChangeListener
import org.koitharu.kotatsu.domain.tracking.TrackingRepository import org.koitharu.kotatsu.domain.tracking.TrackingRepository
import org.koitharu.kotatsu.ui.common.BasePresenter import org.koitharu.kotatsu.ui.common.BasePresenter
import org.koitharu.kotatsu.ui.common.SharedPresenterHolder
import org.koitharu.kotatsu.utils.ext.safe import org.koitharu.kotatsu.utils.ext.safe
import java.io.IOException import java.io.IOException
@InjectViewState @InjectViewState
class MangaDetailsPresenter private constructor() : BasePresenter<MangaDetailsView>(), class MangaDetailsPresenter private constructor(private val key: Int) :
OnHistoryChangeListener, BasePresenter<MangaDetailsView>(), OnHistoryChangeListener, OnFavouritesChangeListener {
OnFavouritesChangeListener {
private lateinit var historyRepository: HistoryRepository private lateinit var historyRepository: HistoryRepository
private lateinit var favouritesRepository: FavouritesRepository private lateinit var favouritesRepository: FavouritesRepository
@@ -55,7 +56,7 @@ class MangaDetailsPresenter private constructor() : BasePresenter<MangaDetailsVi
} ?: throw MangaNotFoundException("Cannot find manga by id") } ?: throw MangaNotFoundException("Cannot find manga by id")
viewState.onMangaUpdated(manga) viewState.onMangaUpdated(manga)
loadDetails(manga, true) loadDetails(manga, true)
} catch (_: CancellationException){ } catch (_: CancellationException) {
} catch (e: Throwable) { } catch (e: Throwable) {
if (BuildConfig.DEBUG) { if (BuildConfig.DEBUG) {
e.printStackTrace() e.printStackTrace()
@@ -83,7 +84,7 @@ class MangaDetailsPresenter private constructor() : BasePresenter<MangaDetailsVi
viewState.onMangaUpdated(data) viewState.onMangaUpdated(data)
this@MangaDetailsPresenter.manga = data this@MangaDetailsPresenter.manga = data
viewState.onNewChaptersChanged(trackingRepository.getNewChaptersCount(manga.id)) viewState.onNewChaptersChanged(trackingRepository.getNewChaptersCount(manga.id))
} catch (_: CancellationException){ } catch (_: CancellationException) {
} catch (e: Throwable) { } catch (e: Throwable) {
if (BuildConfig.DEBUG) { if (BuildConfig.DEBUG) {
e.printStackTrace() e.printStackTrace()
@@ -198,18 +199,12 @@ class MangaDetailsPresenter private constructor() : BasePresenter<MangaDetailsVi
override fun onDestroy() { override fun onDestroy() {
HistoryRepository.unsubscribe(this) HistoryRepository.unsubscribe(this)
FavouritesRepository.unsubscribe(this) FavouritesRepository.unsubscribe(this)
instance = null clear(key)
super.onDestroy() super.onDestroy()
} }
companion object { companion object Holder : SharedPresenterHolder<MangaDetailsPresenter>() {
private var instance: MangaDetailsPresenter? = null override fun onCreatePresenter(key: Int) = MangaDetailsPresenter(key)
fun getInstance(): MangaDetailsPresenter = instance ?: synchronized(this) {
MangaDetailsPresenter().also {
instance = it
}
}
} }
} }

View File

@@ -10,7 +10,9 @@ import org.koitharu.kotatsu.ui.list.MangaListFragment
class RelatedMangaFragment : MangaListFragment<Unit>(), MangaDetailsView { class RelatedMangaFragment : MangaListFragment<Unit>(), MangaDetailsView {
private val presenter by moxyPresenter(factory = MangaDetailsPresenter.Companion::getInstance) private val presenter by moxyPresenter {
MangaDetailsPresenter.getInstance(activity.hashCode())
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)

View File

@@ -38,11 +38,11 @@ class LocalListPresenter : BasePresenter<MangaListView<File>>() {
} }
fun loadList(offset: Int) { fun loadList(offset: Int) {
if (offset != 0) {
viewState.onListAppended(emptyList())
return
}
presenterScope.launch { presenterScope.launch {
if (offset != 0) {
viewState.onListAppended(emptyList())
return@launch
}
viewState.onLoadingStateChanged(true) viewState.onLoadingStateChanged(true)
try { try {
val list = withContext(Dispatchers.IO) { val list = withContext(Dispatchers.IO) {

View File

@@ -75,7 +75,7 @@ class ReaderActivity : BaseFullscreenActivity(), ReaderView, ChaptersDialog.OnCh
?: intent.getParcelableExtra<ReaderState>(EXTRA_STATE) ?: intent.getParcelableExtra<ReaderState>(EXTRA_STATE)
?: let { ?: let {
Toast.makeText(this, R.string.error_occurred, Toast.LENGTH_SHORT).show() Toast.makeText(this, R.string.error_occurred, Toast.LENGTH_SHORT).show()
finish() finishAfterTransition()
return return
} }

View File

@@ -19,7 +19,7 @@ class SearchActivity : BaseActivity(), SearchView.OnQueryTextListener {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
setContentView(R.layout.activity_search) setContentView(R.layout.activity_search)
source = intent.getParcelableExtra(EXTRA_SOURCE) ?: run { source = intent.getParcelableExtra(EXTRA_SOURCE) ?: run {
finish() finishAfterTransition()
return return
} }
val query = intent.getStringExtra(EXTRA_QUERY) val query = intent.getStringExtra(EXTRA_QUERY)

View File

@@ -14,7 +14,7 @@ class GlobalSearchActivity : BaseActivity() {
val query = intent.getStringExtra(EXTRA_QUERY) val query = intent.getStringExtra(EXTRA_QUERY)
if (query == null) { if (query == null) {
finish() finishAfterTransition()
return return
} }

View File

@@ -48,7 +48,7 @@ class ShelfConfigActivity : BaseActivity(), FavouriteCategoriesView,
AppWidgetManager.INVALID_APPWIDGET_ID AppWidgetManager.INVALID_APPWIDGET_ID
) ?: AppWidgetManager.INVALID_APPWIDGET_ID ) ?: AppWidgetManager.INVALID_APPWIDGET_ID
if (appWidgetId == AppWidgetManager.INVALID_APPWIDGET_ID) { if (appWidgetId == AppWidgetManager.INVALID_APPWIDGET_ID) {
finish() finishAfterTransition()
return return
} }
config = AppWidgetConfig.getInstance(this, appWidgetId) config = AppWidgetConfig.getInstance(this, appWidgetId)