Achievements performance improvements

This commit is contained in:
Phillip Thelen 2022-05-27 15:37:54 +02:00
parent 328304b6da
commit f7cc63a774
9 changed files with 64 additions and 79 deletions

View file

@ -36,7 +36,7 @@ interface InventoryRepository : BaseRepository {
fun getOwnedPets(): Flow<List<OwnedPet>>
fun getQuestContent(key: String): Flowable<QuestContent>
fun getQuestContent(keys: List<String>): Flowable<out List<QuestContent>>
fun getQuestContent(keys: List<String>): Flow<List<QuestContent>>
fun getEquipment(searchedKeys: List<String>): Flowable<out List<Equipment>>
fun retrieveInAppRewards(): Flowable<List<ShopItem>>

View file

@ -81,8 +81,8 @@ interface UserRepository : BaseRepository {
fun useCustomization(type: String, category: String?, identifier: String): Flowable<User>
fun retrieveAchievements(): Flowable<List<Achievement>>
fun getAchievements(): Flowable<out List<Achievement>>
fun getQuestAchievements(): Flowable<out List<QuestAchievement>>
fun getAchievements(): Flow<List<Achievement>>
fun getQuestAchievements(): Flow<List<QuestAchievement>>
fun getUserQuestStatus(): Flowable<UserQuestStatus>

View file

@ -31,7 +31,7 @@ class InventoryRepositoryImpl(
userID: String,
var appConfigManager: AppConfigManager
) : BaseRepositoryImpl<InventoryLocalRepository>(localRepository, apiClient, userID), InventoryRepository {
override fun getQuestContent(keys: List<String>): Flowable<out List<QuestContent>> {
override fun getQuestContent(keys: List<String>): Flow<List<QuestContent>> {
return localRepository.getQuestContent(keys)
}

View file

@ -356,11 +356,11 @@ class UserRepositoryImpl(
}
}
override fun getAchievements(): Flowable<out List<Achievement>> {
override fun getAchievements(): Flow<List<Achievement>> {
return localRepository.getAchievements()
}
override fun getQuestAchievements(): Flowable<out List<QuestAchievement>> {
override fun getQuestAchievements(): Flow<List<QuestAchievement>> {
return localRepository.getQuestAchievements(userID)
}

View file

@ -29,7 +29,7 @@ interface InventoryLocalRepository : ContentLocalRepository {
fun getInAppRewards(): Flowable<out List<ShopItem>>
fun getQuestContent(key: String): Flowable<QuestContent>
fun getQuestContent(keys: List<String>): Flowable<out List<QuestContent>>
fun getQuestContent(keys: List<String>): Flow<List<QuestContent>>
fun getEquipment(searchedKeys: List<String>): Flowable<out List<Equipment>>

View file

@ -32,8 +32,8 @@ interface UserLocalRepository : BaseLocalRepository {
fun getSkills(user: User): Flowable<out List<Skill>>
fun getSpecialItems(user: User): Flowable<out List<Skill>>
fun getAchievements(): Flowable<out List<Achievement>>
fun getQuestAchievements(userID: String): Flowable<out List<QuestAchievement>>
fun getAchievements(): Flow<List<Achievement>>
fun getQuestAchievements(userID: String): Flow<List<QuestAchievement>>
fun getUserQuestStatus(userID: String): Flowable<UserQuestStatus>
fun getTeamPlans(userID: String): Flowable<out List<TeamPlan>>
fun getTeamPlan(teamID: String): Flowable<Group>

View file

@ -31,14 +31,12 @@ import java.util.Date
import java.util.Locale
class RealmInventoryLocalRepository(realm: Realm) : RealmContentLocalRepository(realm), InventoryLocalRepository {
override fun getQuestContent(keys: List<String>): Flowable<out List<QuestContent>> {
return RxJavaBridge.toV3Flowable(
realm.where(QuestContent::class.java)
override fun getQuestContent(keys: List<String>): Flow<List<QuestContent>> {
return realm.where(QuestContent::class.java)
.`in`("key", keys.toTypedArray())
.findAll()
.asFlowable()
.toFlow()
.filter { it.isLoaded }
)
}
override fun getQuestContent(key: String): Flowable<QuestContent> {

View file

@ -46,25 +46,21 @@ class RealmUserLocalRepository(realm: Realm) : RealmBaseLocalRepository(realm),
}
}
override fun getAchievements(): Flowable<out List<Achievement>> {
return RxJavaBridge.toV3Flowable(
realm.where(Achievement::class.java)
override fun getAchievements(): Flow<List<Achievement>> {
return realm.where(Achievement::class.java)
.sort("index")
.findAll()
.asFlowable()
.toFlow()
.filter { it.isLoaded }
)
}
override fun getQuestAchievements(userID: String): Flowable<out List<QuestAchievement>> {
return RxJavaBridge.toV3Flowable(
realm.where(User::class.java)
override fun getQuestAchievements(userID: String): Flow<List<QuestAchievement>> {
return realm.where(User::class.java)
.equalTo("id", userID)
.findAll()
.asFlowable()
.toFlow()
.filter { it.isLoaded }
.map { it.first()?.questAchievements ?: emptyList() }
)
}
override fun getTutorialSteps(): Flowable<List<TutorialStep>> = RxJavaBridge.toV3Flowable(

View file

@ -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<FragmentRefreshRecyclerviewBinding>(), SwipeRefreshLayout.OnRefreshListener {
@ -92,64 +95,52 @@ class AchievementsFragment : BaseMainFragment<FragmentRefreshRecyclerviewBinding
binding?.refreshLayout?.setOnRefreshListener(this)
compositeSubscription.add(
userRepository.getAchievements().map { achievements ->
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<Any>()
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<Any>()
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) {