From f7cc63a7743d56b3e32b303a793907d4329b50a8 Mon Sep 17 00:00:00 2001 From: Phillip Thelen Date: Fri, 27 May 2022 15:37:54 +0200 Subject: [PATCH] Achievements performance improvements --- .../habitica/data/InventoryRepository.kt | 2 +- .../android/habitica/data/UserRepository.kt | 4 +- .../implementation/InventoryRepositoryImpl.kt | 2 +- .../data/implementation/UserRepositoryImpl.kt | 4 +- .../data/local/InventoryLocalRepository.kt | 2 +- .../data/local/UserLocalRepository.kt | 4 +- .../RealmInventoryLocalRepository.kt | 8 +- .../RealmUserLocalRepository.kt | 16 ++- .../ui/fragments/AchievementsFragment.kt | 101 ++++++++---------- 9 files changed, 64 insertions(+), 79 deletions(-) diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/data/InventoryRepository.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/data/InventoryRepository.kt index 93ea3f01b..821aaa9c4 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/data/InventoryRepository.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/data/InventoryRepository.kt @@ -36,7 +36,7 @@ interface InventoryRepository : BaseRepository { fun getOwnedPets(): Flow> fun getQuestContent(key: String): Flowable - fun getQuestContent(keys: List): Flowable> + fun getQuestContent(keys: List): Flow> fun getEquipment(searchedKeys: List): Flowable> fun retrieveInAppRewards(): Flowable> diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/data/UserRepository.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/data/UserRepository.kt index 0e37d39f6..3fe9278b5 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/data/UserRepository.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/data/UserRepository.kt @@ -81,8 +81,8 @@ interface UserRepository : BaseRepository { fun useCustomization(type: String, category: String?, identifier: String): Flowable fun retrieveAchievements(): Flowable> - fun getAchievements(): Flowable> - fun getQuestAchievements(): Flowable> + fun getAchievements(): Flow> + fun getQuestAchievements(): Flow> fun getUserQuestStatus(): Flowable diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/InventoryRepositoryImpl.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/InventoryRepositoryImpl.kt index 7e0e65054..2b57c0dce 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/InventoryRepositoryImpl.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/InventoryRepositoryImpl.kt @@ -31,7 +31,7 @@ class InventoryRepositoryImpl( userID: String, var appConfigManager: AppConfigManager ) : BaseRepositoryImpl(localRepository, apiClient, userID), InventoryRepository { - override fun getQuestContent(keys: List): Flowable> { + override fun getQuestContent(keys: List): Flow> { return localRepository.getQuestContent(keys) } diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/UserRepositoryImpl.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/UserRepositoryImpl.kt index 6fbe503b4..9d4f1ce9f 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/UserRepositoryImpl.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/UserRepositoryImpl.kt @@ -356,11 +356,11 @@ class UserRepositoryImpl( } } - override fun getAchievements(): Flowable> { + override fun getAchievements(): Flow> { return localRepository.getAchievements() } - override fun getQuestAchievements(): Flowable> { + override fun getQuestAchievements(): Flow> { return localRepository.getQuestAchievements(userID) } diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/InventoryLocalRepository.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/InventoryLocalRepository.kt index 94236bf05..68300cea3 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/InventoryLocalRepository.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/InventoryLocalRepository.kt @@ -29,7 +29,7 @@ interface InventoryLocalRepository : ContentLocalRepository { fun getInAppRewards(): Flowable> fun getQuestContent(key: String): Flowable - fun getQuestContent(keys: List): Flowable> + fun getQuestContent(keys: List): Flow> fun getEquipment(searchedKeys: List): Flowable> diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/UserLocalRepository.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/UserLocalRepository.kt index 775339b2f..3490b1a8d 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/UserLocalRepository.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/UserLocalRepository.kt @@ -32,8 +32,8 @@ interface UserLocalRepository : BaseLocalRepository { fun getSkills(user: User): Flowable> fun getSpecialItems(user: User): Flowable> - fun getAchievements(): Flowable> - fun getQuestAchievements(userID: String): Flowable> + fun getAchievements(): Flow> + fun getQuestAchievements(userID: String): Flow> fun getUserQuestStatus(userID: String): Flowable fun getTeamPlans(userID: String): Flowable> fun getTeamPlan(teamID: String): Flowable diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/implementation/RealmInventoryLocalRepository.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/implementation/RealmInventoryLocalRepository.kt index 3afd97dfb..98f642082 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/implementation/RealmInventoryLocalRepository.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/implementation/RealmInventoryLocalRepository.kt @@ -31,14 +31,12 @@ import java.util.Date import java.util.Locale class RealmInventoryLocalRepository(realm: Realm) : RealmContentLocalRepository(realm), InventoryLocalRepository { - override fun getQuestContent(keys: List): Flowable> { - return RxJavaBridge.toV3Flowable( - realm.where(QuestContent::class.java) + override fun getQuestContent(keys: List): Flow> { + return realm.where(QuestContent::class.java) .`in`("key", keys.toTypedArray()) .findAll() - .asFlowable() + .toFlow() .filter { it.isLoaded } - ) } override fun getQuestContent(key: String): Flowable { diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/implementation/RealmUserLocalRepository.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/implementation/RealmUserLocalRepository.kt index 96353641f..d3f40a27b 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/implementation/RealmUserLocalRepository.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/implementation/RealmUserLocalRepository.kt @@ -46,25 +46,21 @@ class RealmUserLocalRepository(realm: Realm) : RealmBaseLocalRepository(realm), } } - override fun getAchievements(): Flowable> { - return RxJavaBridge.toV3Flowable( - realm.where(Achievement::class.java) + override fun getAchievements(): Flow> { + return realm.where(Achievement::class.java) .sort("index") .findAll() - .asFlowable() + .toFlow() .filter { it.isLoaded } - ) } - override fun getQuestAchievements(userID: String): Flowable> { - return RxJavaBridge.toV3Flowable( - realm.where(User::class.java) + override fun getQuestAchievements(userID: String): Flow> { + return realm.where(User::class.java) .equalTo("id", userID) .findAll() - .asFlowable() + .toFlow() .filter { it.isLoaded } .map { it.first()?.questAchievements ?: emptyList() } - ) } override fun getTutorialSteps(): Flowable> = RxJavaBridge.toV3Flowable( diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/AchievementsFragment.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/AchievementsFragment.kt index c4622c0b7..a7a760544 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/AchievementsFragment.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/AchievementsFragment.kt @@ -10,6 +10,7 @@ import android.view.View import android.view.ViewGroup import androidx.appcompat.widget.Toolbar import androidx.core.content.ContextCompat +import androidx.lifecycle.lifecycleScope import androidx.recyclerview.widget.GridLayoutManager import androidx.swiperefreshlayout.widget.SwipeRefreshLayout import com.habitrpg.android.habitica.R @@ -20,8 +21,10 @@ import com.habitrpg.android.habitica.helpers.RxErrorHandler import com.habitrpg.android.habitica.ui.adapter.AchievementsAdapter import com.habitrpg.android.habitica.ui.helpers.ToolbarColorHelper import com.habitrpg.android.habitica.ui.viewmodels.MainUserViewModel -import io.reactivex.rxjava3.kotlin.Flowables -import io.reactivex.rxjava3.kotlin.combineLatest +import kotlinx.coroutines.flow.combine +import kotlinx.coroutines.flow.firstOrNull +import kotlinx.coroutines.flow.map +import kotlinx.coroutines.launch import javax.inject.Inject class AchievementsFragment : BaseMainFragment(), SwipeRefreshLayout.OnRefreshListener { @@ -92,64 +95,52 @@ class AchievementsFragment : BaseMainFragment - achievements.sortedBy { - if (it.category == "onboarding") { - it.index - } else { - (it.category?.first()?.toInt() ?: 2) * it.index + lifecycleScope.launch { + userRepository.getAchievements().combine(userRepository.getQuestAchievements()) { achievements, questAchievements -> + return@combine Pair(achievements, questAchievements) + }.combine(userRepository.getQuestAchievements() + .map { it.mapNotNull { achievement -> achievement.questKey } } + .map { inventoryRepository.getQuestContent(it).firstOrNull() }) { achievements, content -> + Pair(achievements, content) + }.collect { + val achievements = it.first.first + val entries = mutableListOf() + var lastCategory = "" + achievements.forEach { achievement -> + val categoryIdentifier = achievement.category ?: "" + if (categoryIdentifier != lastCategory) { + val category = Pair( + categoryIdentifier, + achievements.count { check -> + check.category == categoryIdentifier && check.earned + } + ) + entries.add(category) + lastCategory = categoryIdentifier } + entries.add(achievement) } - }.combineLatest( - Flowables.combineLatest( - userRepository.getQuestAchievements(), - userRepository.getQuestAchievements() - .map { it.mapNotNull { achievement -> achievement.questKey } } - .flatMap { inventoryRepository.getQuestContent(it) } + val questAchievements = it.first.second + entries.add(Pair("Quests completed", questAchievements.size)) + entries.addAll( + questAchievements.map { achievement -> + val questContent = it.second?.firstOrNull { achievement.questKey == it.key } + achievement.title = questContent?.text + achievement + } ) - ).subscribe( - { - val achievements = it.first - val entries = mutableListOf() - var lastCategory = "" - achievements.forEach { achievement -> - val categoryIdentifier = achievement.category ?: "" - if (categoryIdentifier != lastCategory) { - val category = Pair( - categoryIdentifier, - achievements.count { check -> - check.category == categoryIdentifier && check.earned - } - ) - entries.add(category) - lastCategory = categoryIdentifier - } - entries.add(achievement) - } - val questAchievements = it.second - entries.add(Pair("Quests completed", questAchievements.first.size)) - entries.addAll( - questAchievements.first.map { achievement -> - val questContent = questAchievements.second.firstOrNull { achievement.questKey == it.key } - achievement.title = questContent?.text - achievement - } - ) - val user = userViewModel.user.value - val challengeAchievementCount = user?.challengeAchievements?.size ?: 0 - if (challengeAchievementCount > 0) { - entries.add(Pair("Challenges won", challengeAchievementCount)) - user?.challengeAchievements?.let { it1 -> entries.addAll(it1) } - } + val user = userViewModel.user.value + val challengeAchievementCount = user?.challengeAchievements?.size ?: 0 + if (challengeAchievementCount > 0) { + entries.add(Pair("Challenges won", challengeAchievementCount)) + user?.challengeAchievements?.let { it1 -> entries.addAll(it1) } + } - adapter.entries = entries - adapter.notifyDataSetChanged() - }, - RxErrorHandler.handleEmptyError() - ) - ) + adapter.entries = entries + adapter.notifyDataSetChanged() + } + } } override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {