+ get() = subject
+
+ fun emit(count: Int) {
+ subject.onNext(count)
+ }
+}
diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/base/fragment/BaseRxFragment.java b/app/src/main/java/eu/kanade/tachiyomi/ui/base/fragment/BaseRxFragment.java
index 5a65182071..84044cdc8c 100644
--- a/app/src/main/java/eu/kanade/tachiyomi/ui/base/fragment/BaseRxFragment.java
+++ b/app/src/main/java/eu/kanade/tachiyomi/ui/base/fragment/BaseRxFragment.java
@@ -12,7 +12,7 @@ import nucleus.view.PresenterLifecycleDelegate;
import nucleus.view.ViewWithPresenter;
/**
- * This class is an example of how an activity could controls it's presenter.
+ * This view is an example of how a view should control it's presenter.
* You can inherit from this class or copy/paste this class's code to
* create your own view implementation.
*
@@ -87,12 +87,11 @@ public abstract class BaseRxFragment extends BaseFragment i
@Override
public void onPause() {
super.onPause();
- presenterDelegate.onPause(getActivity().isFinishing() || shouldDestroyPresenter(this));
+ presenterDelegate.onPause(getActivity().isFinishing() || isRemoving(this));
}
- private boolean shouldDestroyPresenter(Fragment fragment) {
- if (fragment == null) return false;
- else return fragment.isRemoving() || shouldDestroyPresenter(fragment.getParentFragment());
+ private static boolean isRemoving(Fragment fragment) {
+ Fragment parent = fragment.getParentFragment();
+ return fragment.isRemoving() || (parent != null && isRemoving(parent));
}
-
-}
\ No newline at end of file
+}
diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/base/presenter/BasePresenter.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/base/presenter/BasePresenter.kt
index c361446c97..bd205f72b7 100644
--- a/app/src/main/java/eu/kanade/tachiyomi/ui/base/presenter/BasePresenter.kt
+++ b/app/src/main/java/eu/kanade/tachiyomi/ui/base/presenter/BasePresenter.kt
@@ -3,6 +3,7 @@ package eu.kanade.tachiyomi.ui.base.presenter
import android.content.Context
import nucleus.view.ViewWithPresenter
import org.greenrobot.eventbus.EventBus
+import rx.Observable
open class BasePresenter> : RxPresenter() {
@@ -16,4 +17,13 @@ open class BasePresenter> : RxPresenter() {
EventBus.getDefault().unregister(this)
}
+ fun Observable.subscribeFirst(onNext: (V, T) -> Unit, onError: ((V, Throwable) -> Unit)? = null)
+ = compose(deliverFirst()).subscribe(split(onNext, onError))
+
+ fun Observable.subscribeLatestCache(onNext: (V, T) -> Unit, onError: ((V, Throwable) -> Unit)? = null)
+ = compose(deliverLatestCache()).subscribe(split(onNext, onError))
+
+ fun Observable.subscribeReplay(onNext: (V, T) -> Unit, onError: ((V, Throwable) -> Unit)? = null)
+ = compose(deliverReplay()).subscribe(split(onNext, onError))
+
}
diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaActivity.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaActivity.kt
index 47c092bd03..76eb210ee6 100644
--- a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaActivity.kt
+++ b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaActivity.kt
@@ -13,15 +13,16 @@ import android.support.v4.app.FragmentPagerAdapter
import android.support.v4.content.ContextCompat
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.database.models.Manga
+import eu.kanade.tachiyomi.event.MangaEvent
import eu.kanade.tachiyomi.ui.base.activity.BaseRxActivity
import eu.kanade.tachiyomi.ui.manga.chapter.ChaptersFragment
import eu.kanade.tachiyomi.ui.manga.info.MangaInfoFragment
import eu.kanade.tachiyomi.ui.manga.myanimelist.MyAnimeListFragment
+import eu.kanade.tachiyomi.util.SharedData
import kotlinx.android.synthetic.main.activity_manga.*
import kotlinx.android.synthetic.main.tab_layout.*
import kotlinx.android.synthetic.main.toolbar.*
import nucleus.factory.RequiresPresenter
-import org.greenrobot.eventbus.EventBus
@RequiresPresenter(MangaPresenter::class)
class MangaActivity : BaseRxActivity() {
@@ -33,11 +34,9 @@ class MangaActivity : BaseRxActivity() {
val CHAPTERS_FRAGMENT = 1
val MYANIMELIST_FRAGMENT = 2
- fun newIntent(context: Context, manga: Manga?): Intent {
+ fun newIntent(context: Context, manga: Manga): Intent {
val intent = Intent(context, MangaActivity::class.java)
- if (manga != null) {
- EventBus.getDefault().postSticky(manga)
- }
+ SharedData.put(MangaEvent(manga))
return intent
}
}
diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaPresenter.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaPresenter.kt
index 3b68a39869..d7d1867ec1 100644
--- a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaPresenter.kt
+++ b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaPresenter.kt
@@ -4,11 +4,10 @@ import android.os.Bundle
import eu.kanade.tachiyomi.data.database.DatabaseHelper
import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.data.mangasync.MangaSyncManager
+import eu.kanade.tachiyomi.event.ChapterCountEvent
import eu.kanade.tachiyomi.event.MangaEvent
import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter
-import org.greenrobot.eventbus.EventBus
-import org.greenrobot.eventbus.Subscribe
-import org.greenrobot.eventbus.ThreadMode
+import eu.kanade.tachiyomi.util.SharedData
import rx.Observable
import javax.inject.Inject
@@ -37,32 +36,26 @@ class MangaPresenter : BasePresenter() {
*/
private val MANGA_KEY = "manga_key"
- /**
- * Id of the restartable that notifies the view of a manga.
- */
- private val GET_MANGA = 1
-
override fun onCreate(savedState: Bundle?) {
super.onCreate(savedState)
- if (savedState != null) {
- manga = savedState.getSerializable(MANGA_KEY) as Manga
- }
-
- restartableLatestCache(GET_MANGA,
- { Observable.just(manga)
- .doOnNext { EventBus.getDefault().postSticky(MangaEvent(it)) } },
- { view, manga -> view.onSetManga(manga) })
-
if (savedState == null) {
- registerForEvents()
+ manga = SharedData.get(MangaEvent::class.java)!!.manga
+ } else {
+ manga = savedState.getSerializable(MANGA_KEY) as Manga
+ SharedData.put(MangaEvent(manga))
}
+
+ // Prepare a subject to communicate the chapters and info presenters for the chapter count.
+ SharedData.put(ChapterCountEvent())
+
+ add(Observable.just(manga)
+ .subscribeLatestCache({ view, manga -> view.onSetManga(manga) }))
}
override fun onDestroy() {
- // Avoid new instances receiving wrong manga
- EventBus.getDefault().removeStickyEvent(MangaEvent::class.java)
-
+ SharedData.remove(MangaEvent::class.java)
+ SharedData.remove(ChapterCountEvent::class.java)
super.onDestroy()
}
@@ -71,12 +64,4 @@ class MangaPresenter : BasePresenter() {
super.onSave(state)
}
- @Subscribe(sticky = true, threadMode = ThreadMode.MAIN)
- fun onEvent(manga: Manga) {
- EventBus.getDefault().removeStickyEvent(manga)
- unregisterForEvents()
- this.manga = manga
- start(GET_MANGA)
- }
-
}
diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/chapter/ChaptersPresenter.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/chapter/ChaptersPresenter.kt
index 97a68756d4..90bdbaa284 100644
--- a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/chapter/ChaptersPresenter.kt
+++ b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/chapter/ChaptersPresenter.kt
@@ -15,9 +15,8 @@ import eu.kanade.tachiyomi.event.DownloadChaptersEvent
import eu.kanade.tachiyomi.event.MangaEvent
import eu.kanade.tachiyomi.event.ReaderEvent
import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter
+import eu.kanade.tachiyomi.util.SharedData
import org.greenrobot.eventbus.EventBus
-import org.greenrobot.eventbus.Subscribe
-import org.greenrobot.eventbus.ThreadMode
import rx.Observable
import rx.android.schedulers.AndroidSchedulers
import rx.schedulers.Schedulers
@@ -47,20 +46,15 @@ class ChaptersPresenter : BasePresenter() {
var hasRequested: Boolean = false
private set
- private val GET_MANGA = 1
- private val DB_CHAPTERS = 2
- private val FETCH_CHAPTERS = 3
- private val CHAPTER_STATUS_CHANGES = 4
+ private val DB_CHAPTERS = 1
+ private val FETCH_CHAPTERS = 2
+ private val CHAPTER_STATUS_CHANGES = 3
override fun onCreate(savedState: Bundle?) {
super.onCreate(savedState)
chaptersSubject = PublishSubject.create()
- startableLatestCache(GET_MANGA,
- { Observable.just(manga) },
- { view, manga -> view.onNextManga(manga) })
-
startableLatestCache(DB_CHAPTERS,
{ getDbChaptersObs() },
{ view, chapters -> view.onNextChapters(chapters) })
@@ -75,36 +69,26 @@ class ChaptersPresenter : BasePresenter() {
{ view, download -> view.onChapterStatusChange(download) },
{ view, error -> Timber.e(error.cause, error.message) })
- registerForEvents()
- }
+ manga = SharedData.get(MangaEvent::class.java)!!.manga
+ add(Observable.just(manga)
+ .subscribeLatestCache({ view, manga -> view.onNextManga(manga) }))
- override fun onDestroy() {
- unregisterForEvents()
- EventBus.getDefault().removeStickyEvent(ChapterCountEvent::class.java)
- super.onDestroy()
- }
+ source = sourceManager.get(manga.source)!!
+ start(DB_CHAPTERS)
- @Subscribe(sticky = true, threadMode = ThreadMode.MAIN)
- fun onEvent(event: MangaEvent) {
- this.manga = event.manga
- start(GET_MANGA)
-
- if (isUnsubscribed(DB_CHAPTERS)) {
- source = sourceManager.get(manga.source)!!
- start(DB_CHAPTERS)
-
- add(db.getChapters(manga).asRxObservable()
- .subscribeOn(Schedulers.io())
- .doOnNext { chapters ->
- this.chapters = chapters
- EventBus.getDefault().postSticky(ChapterCountEvent(chapters.size))
- for (chapter in chapters) {
- setChapterStatus(chapter)
- }
- start(CHAPTER_STATUS_CHANGES)
+ add(db.getChapters(manga).asRxObservable()
+ .subscribeOn(Schedulers.io())
+ .doOnNext { chapters ->
+ this.chapters = chapters
+ SharedData.get(ChapterCountEvent::class.java)?.let {
+ it.emit(chapters.size)
}
- .subscribe { chaptersSubject.onNext(it) })
- }
+ for (chapter in chapters) {
+ setChapterStatus(chapter)
+ }
+ start(CHAPTER_STATUS_CHANGES)
+ }
+ .subscribe { chaptersSubject.onNext(it) })
}
fun fetchChaptersFromSource() {
@@ -179,7 +163,7 @@ class ChaptersPresenter : BasePresenter() {
}
fun onOpenChapter(chapter: Chapter) {
- EventBus.getDefault().postSticky(ReaderEvent(manga, chapter))
+ SharedData.put(ReaderEvent(manga, chapter))
}
fun getNextUnreadChapter(): Chapter? {
diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/info/MangaInfoPresenter.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/info/MangaInfoPresenter.kt
index d472e829cb..e2136cc249 100644
--- a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/info/MangaInfoPresenter.kt
+++ b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/info/MangaInfoPresenter.kt
@@ -9,8 +9,7 @@ import eu.kanade.tachiyomi.data.source.base.Source
import eu.kanade.tachiyomi.event.ChapterCountEvent
import eu.kanade.tachiyomi.event.MangaEvent
import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter
-import org.greenrobot.eventbus.Subscribe
-import org.greenrobot.eventbus.ThreadMode
+import eu.kanade.tachiyomi.util.SharedData
import rx.Observable
import rx.android.schedulers.AndroidSchedulers
import rx.schedulers.Schedulers
@@ -50,11 +49,6 @@ class MangaInfoPresenter : BasePresenter() {
*/
@Inject lateinit var coverCache: CoverCache
- /**
- * Count of chapters.
- */
- private var count = -1
-
/**
* The id of the restartable.
*/
@@ -63,12 +57,7 @@ class MangaInfoPresenter : BasePresenter() {
/**
* The id of the restartable.
*/
- private val GET_CHAPTER_COUNT = 2
-
- /**
- * The id of the restartable.
- */
- private val FETCH_MANGA_INFO = 3
+ private val FETCH_MANGA_INFO = 2
override fun onCreate(savedState: Bundle?) {
super.onCreate(savedState)
@@ -78,39 +67,19 @@ class MangaInfoPresenter : BasePresenter() {
{ Observable.just(manga) },
{ view, manga -> view.onNextManga(manga, source) })
- // Update chapter count.
- startableLatestCache(GET_CHAPTER_COUNT,
- { Observable.just(count) },
- { view, count -> view.setChapterCount(count) })
-
// Fetch manga info from source.
startableFirst(FETCH_MANGA_INFO,
{ fetchMangaObs() },
{ view, manga -> view.onFetchMangaDone() },
{ view, error -> view.onFetchMangaError() })
- // Listen for events.
- registerForEvents()
- }
-
- override fun onDestroy() {
- unregisterForEvents()
- super.onDestroy()
- }
-
- @Subscribe(sticky = true, threadMode = ThreadMode.MAIN)
- fun onEvent(event: MangaEvent) {
- manga = event.manga
+ manga = SharedData.get(MangaEvent::class.java)!!.manga
source = sourceManager.get(manga.source)!!
refreshManga()
- }
- @Subscribe(sticky = true, threadMode = ThreadMode.MAIN)
- fun onEvent(event: ChapterCountEvent) {
- if (count != event.count) {
- count = event.count
- // Update chapter count
- start(GET_CHAPTER_COUNT)
+ // Update chapter count
+ SharedData.get(ChapterCountEvent::class.java)?.let {
+ add(it.observable.subscribeLatestCache({ view, count -> view.setChapterCount(count) }))
}
}
diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/myanimelist/MyAnimeListPresenter.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/myanimelist/MyAnimeListPresenter.kt
index ab6b4be95c..510a57ca09 100644
--- a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/myanimelist/MyAnimeListPresenter.kt
+++ b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/myanimelist/MyAnimeListPresenter.kt
@@ -9,9 +9,8 @@ import eu.kanade.tachiyomi.data.database.models.MangaSync
import eu.kanade.tachiyomi.data.mangasync.MangaSyncManager
import eu.kanade.tachiyomi.event.MangaEvent
import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter
+import eu.kanade.tachiyomi.util.SharedData
import eu.kanade.tachiyomi.util.toast
-import org.greenrobot.eventbus.Subscribe
-import org.greenrobot.eventbus.ThreadMode
import rx.Observable
import rx.android.schedulers.AndroidSchedulers
import rx.schedulers.Schedulers
@@ -59,17 +58,7 @@ class MyAnimeListPresenter : BasePresenter() {
{ view, result -> view.onRefreshDone() },
{ view, error -> view.onRefreshError(error) })
- registerForEvents()
- }
-
- override fun onDestroy() {
- unregisterForEvents()
- super.onDestroy()
- }
-
- @Subscribe(sticky = true, threadMode = ThreadMode.MAIN)
- fun onEvent(event: MangaEvent) {
- manga = event.manga
+ manga = SharedData.get(MangaEvent::class.java)!!.manga
start(GET_MANGA_SYNC)
}
diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderActivity.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderActivity.kt
index a325b74f59..ff7a129400 100644
--- a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderActivity.kt
+++ b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderActivity.kt
@@ -36,6 +36,7 @@ import kotlinx.android.synthetic.main.reader_menu.*
import nucleus.factory.RequiresPresenter
import rx.Subscription
import rx.subscriptions.CompositeSubscription
+import timber.log.Timber
import java.text.DecimalFormat
@RequiresPresenter(ReaderPresenter::class)
@@ -83,7 +84,7 @@ class ReaderActivity : BaseRxActivity() {
val preferences: PreferencesHelper
get() = presenter.prefs
- public override fun onCreate(savedState: Bundle?) {
+ override fun onCreate(savedState: Bundle?) {
super.onCreate(savedState)
setContentView(R.layout.activity_reader)
@@ -189,8 +190,9 @@ class ReaderActivity : BaseRxActivity() {
}
}
- fun onChapterError() {
+ fun onChapterError(error: Throwable) {
finish()
+ Timber.e(error, error.message)
toast(R.string.page_list_error)
}
diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderPresenter.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderPresenter.kt
index 44a9004034..1a08cf1f82 100644
--- a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderPresenter.kt
+++ b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderPresenter.kt
@@ -17,9 +17,7 @@ import eu.kanade.tachiyomi.data.source.base.Source
import eu.kanade.tachiyomi.data.source.model.Page
import eu.kanade.tachiyomi.event.ReaderEvent
import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter
-import org.greenrobot.eventbus.EventBus
-import org.greenrobot.eventbus.Subscribe
-import org.greenrobot.eventbus.ThreadMode
+import eu.kanade.tachiyomi.util.SharedData
import rx.Observable
import rx.Subscription
import rx.android.schedulers.AndroidSchedulers
@@ -72,19 +70,26 @@ class ReaderPresenter : BasePresenter() {
override fun onCreate(savedState: Bundle?) {
super.onCreate(savedState)
- if (savedState != null) {
+ if (savedState == null) {
+ val event = SharedData.remove(ReaderEvent::class.java)!!
+ manga = event.manga
+ chapter = event.chapter
+ } else {
manga = savedState.getSerializable(MANGA_KEY) as Manga
- source = sourceManager.get(manga.source)!!
chapter = savedState.getSerializable(CHAPTER_KEY) as Chapter
requestedPage = savedState.getInt(PAGE_KEY)
- initializeSubjects()
}
+ source = sourceManager.get(manga.source)!!
+
+ initializeSubjects()
+
startableLatestCache(GET_ADJACENT_CHAPTERS,
{ getAdjacentChaptersObservable() },
{ view, pair -> view.onAdjacentChapters(pair.first, pair.second) })
- startable(PRELOAD_NEXT_CHAPTER, { getPreloadNextChapterObservable() },
+ startable(PRELOAD_NEXT_CHAPTER,
+ { getPreloadNextChapterObservable() },
{ },
{ error -> Timber.e("Error preloading chapter") })
@@ -95,38 +100,24 @@ class ReaderPresenter : BasePresenter() {
restartableLatestCache(GET_PAGE_LIST,
{ getPageListObservable(chapter) },
{ view, chapter -> view.onChapterReady(manga, chapter, currentPage) },
- { view, error -> view.onChapterError() })
+ { view, error -> view.onChapterError(error) })
if (savedState == null) {
- registerForEvents()
+ loadChapter(chapter)
+ if (prefs.autoUpdateMangaSync()) {
+ start(GET_MANGA_SYNC)
+ }
}
}
- override fun onDestroy() {
- unregisterForEvents()
- super.onDestroy()
- }
-
override fun onSave(state: Bundle) {
onChapterLeft()
state.putSerializable(MANGA_KEY, manga)
state.putSerializable(CHAPTER_KEY, chapter)
- state.putSerializable(PAGE_KEY, requestedPage)
+ state.putSerializable(PAGE_KEY, currentPage?.pageNumber ?: 0)
super.onSave(state)
}
- @Subscribe(sticky = true, threadMode = ThreadMode.MAIN)
- fun onEvent(event: ReaderEvent) {
- EventBus.getDefault().removeStickyEvent(event)
- manga = event.manga
- source = sourceManager.get(manga.source)!!
- initializeSubjects()
- loadChapter(event.chapter)
- if (prefs.autoUpdateMangaSync()) {
- start(GET_MANGA_SYNC)
- }
- }
-
private fun initializeSubjects() {
// Listen for pages initialization events
pageInitializerSubject = PublishSubject.create()
diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/recent/RecentChaptersPresenter.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/recent/RecentChaptersPresenter.kt
index ab9e86be25..55e2f49876 100644
--- a/app/src/main/java/eu/kanade/tachiyomi/ui/recent/RecentChaptersPresenter.kt
+++ b/app/src/main/java/eu/kanade/tachiyomi/ui/recent/RecentChaptersPresenter.kt
@@ -12,6 +12,7 @@ import eu.kanade.tachiyomi.data.source.SourceManager
import eu.kanade.tachiyomi.event.DownloadChaptersEvent
import eu.kanade.tachiyomi.event.ReaderEvent
import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter
+import eu.kanade.tachiyomi.util.SharedData
import org.greenrobot.eventbus.EventBus
import rx.Observable
import rx.android.schedulers.AndroidSchedulers
@@ -256,7 +257,7 @@ class RecentChaptersPresenter : BasePresenter() {
* @param item chapter that is opened
*/
fun onOpenChapter(item: MangaChapter) {
- EventBus.getDefault().postSticky(ReaderEvent(item.manga, item.chapter))
+ SharedData.put(ReaderEvent(item.manga, item.chapter))
}
/**
diff --git a/app/src/main/java/eu/kanade/tachiyomi/util/SharedData.kt b/app/src/main/java/eu/kanade/tachiyomi/util/SharedData.kt
new file mode 100644
index 0000000000..6c0daedc23
--- /dev/null
+++ b/app/src/main/java/eu/kanade/tachiyomi/util/SharedData.kt
@@ -0,0 +1,45 @@
+package eu.kanade.tachiyomi.util
+
+import java.util.*
+
+/**
+ * This singleton is used to share some objects within the application, useful to communicate
+ * different parts of the app.
+ *
+ * It stores the objects in a map using the type of the object as key, so that only one object per
+ * class is stored at once.
+ */
+object SharedData {
+
+ /**
+ * Map where the objects are saved.
+ */
+ private val map = HashMap, Any>()
+
+ /**
+ * Publish an object to the shared data.
+ *
+ * @param data the object to put.
+ */
+ fun put(data: T) {
+ map.put(data.javaClass, data)
+ }
+
+ /**
+ * Retrieves an object from the shared data.
+ *
+ * @param classType the class of the object to retrieve.
+ * @return an object of type T or null if it's not found.
+ */
+ @Suppress("UNCHECKED_CAST")
+ fun get(classType: Class) = map[classType] as? T
+
+ /**
+ * Removes an object from the shared data.
+ *
+ * @param classType the class of the object to remove.
+ * @return the object removed, null otherwise.
+ */
+ fun remove(classType: Class) = get(classType)?.apply { map.remove(classType) }
+
+}