summaryrefslogtreecommitdiff
path: root/src/android
diff options
context:
space:
mode:
authorGravatar t8952023-12-10 20:54:00 -0500
committerGravatar t8952023-12-12 17:25:37 -0500
commitf9d48271029142695d29e065c3449c57ea7c7ded (patch)
treece206083ab074d8dbbc1cb66791a625003cba61c /src/android
parentandroid: Collect latest information for games list (diff)
downloadyuzu-f9d48271029142695d29e065c3449c57ea7c7ded.tar.gz
yuzu-f9d48271029142695d29e065c3449c57ea7c7ded.tar.xz
yuzu-f9d48271029142695d29e065c3449c57ea7c7ded.zip
android: Fix games list loading thread safety
Previously we relied on a stateflow for reloading state. Now we use an atomic boolean.
Diffstat (limited to 'src/android')
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/model/GamesViewModel.kt74
1 files changed, 38 insertions, 36 deletions
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/GamesViewModel.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/GamesViewModel.kt
index eaec09b24..d19f20dc2 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/GamesViewModel.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/GamesViewModel.kt
@@ -20,8 +20,8 @@ import kotlinx.serialization.json.Json
20import org.yuzu.yuzu_emu.NativeLibrary 20import org.yuzu.yuzu_emu.NativeLibrary
21import org.yuzu.yuzu_emu.YuzuApplication 21import org.yuzu.yuzu_emu.YuzuApplication
22import org.yuzu.yuzu_emu.utils.GameHelper 22import org.yuzu.yuzu_emu.utils.GameHelper
23import org.yuzu.yuzu_emu.utils.GameMetadata
24import org.yuzu.yuzu_emu.utils.NativeConfig 23import org.yuzu.yuzu_emu.utils.NativeConfig
24import java.util.concurrent.atomic.AtomicBoolean
25 25
26class GamesViewModel : ViewModel() { 26class GamesViewModel : ViewModel() {
27 val games: StateFlow<List<Game>> get() = _games 27 val games: StateFlow<List<Game>> get() = _games
@@ -33,6 +33,8 @@ class GamesViewModel : ViewModel() {
33 val isReloading: StateFlow<Boolean> get() = _isReloading 33 val isReloading: StateFlow<Boolean> get() = _isReloading
34 private val _isReloading = MutableStateFlow(false) 34 private val _isReloading = MutableStateFlow(false)
35 35
36 private val reloading = AtomicBoolean(false)
37
36 val shouldSwapData: StateFlow<Boolean> get() = _shouldSwapData 38 val shouldSwapData: StateFlow<Boolean> get() = _shouldSwapData
37 private val _shouldSwapData = MutableStateFlow(false) 39 private val _shouldSwapData = MutableStateFlow(false)
38 40
@@ -49,38 +51,8 @@ class GamesViewModel : ViewModel() {
49 // Ensure keys are loaded so that ROM metadata can be decrypted. 51 // Ensure keys are loaded so that ROM metadata can be decrypted.
50 NativeLibrary.reloadKeys() 52 NativeLibrary.reloadKeys()
51 53
52 // Retrieve list of cached games 54 getGameDirs()
53 val storedGames = PreferenceManager.getDefaultSharedPreferences(YuzuApplication.appContext) 55 reloadGames(directoriesChanged = false, firstStartup = true)
54 .getStringSet(GameHelper.KEY_GAMES, emptySet())
55
56 viewModelScope.launch {
57 withContext(Dispatchers.IO) {
58 getGameDirs()
59 if (storedGames!!.isNotEmpty()) {
60 val deserializedGames = mutableSetOf<Game>()
61 storedGames.forEach {
62 val game: Game
63 try {
64 game = Json.decodeFromString(it)
65 } catch (e: Exception) {
66 // We don't care about any errors related to parsing the game cache
67 return@forEach
68 }
69
70 val gameExists =
71 DocumentFile.fromSingleUri(
72 YuzuApplication.appContext,
73 Uri.parse(game.path)
74 )?.exists()
75 if (gameExists == true) {
76 deserializedGames.add(game)
77 }
78 }
79 setGames(deserializedGames.toList())
80 }
81 reloadGames(false)
82 }
83 }
84 } 56 }
85 57
86 fun setGames(games: List<Game>) { 58 fun setGames(games: List<Game>) {
@@ -110,16 +82,46 @@ class GamesViewModel : ViewModel() {
110 _searchFocused.value = searchFocused 82 _searchFocused.value = searchFocused
111 } 83 }
112 84
113 fun reloadGames(directoriesChanged: Boolean) { 85 fun reloadGames(directoriesChanged: Boolean, firstStartup: Boolean = false) {
114 if (isReloading.value) { 86 if (reloading.get()) {
115 return 87 return
116 } 88 }
89 reloading.set(true)
117 _isReloading.value = true 90 _isReloading.value = true
118 91
119 viewModelScope.launch { 92 viewModelScope.launch {
120 withContext(Dispatchers.IO) { 93 withContext(Dispatchers.IO) {
121 GameMetadata.resetMetadata() 94 if (firstStartup) {
95 // Retrieve list of cached games
96 val storedGames =
97 PreferenceManager.getDefaultSharedPreferences(YuzuApplication.appContext)
98 .getStringSet(GameHelper.KEY_GAMES, emptySet())
99 if (storedGames!!.isNotEmpty()) {
100 val deserializedGames = mutableSetOf<Game>()
101 storedGames.forEach {
102 val game: Game
103 try {
104 game = Json.decodeFromString(it)
105 } catch (e: Exception) {
106 // We don't care about any errors related to parsing the game cache
107 return@forEach
108 }
109
110 val gameExists =
111 DocumentFile.fromSingleUri(
112 YuzuApplication.appContext,
113 Uri.parse(game.path)
114 )?.exists()
115 if (gameExists == true) {
116 deserializedGames.add(game)
117 }
118 }
119 setGames(deserializedGames.toList())
120 }
121 }
122
122 setGames(GameHelper.getGames()) 123 setGames(GameHelper.getGames())
124 reloading.set(false)
123 _isReloading.value = false 125 _isReloading.value = false
124 126
125 if (directoriesChanged) { 127 if (directoriesChanged) {