Как собрать потоки из двух разных таблиц комнаты и объединить данные для отображения в recyclerview в Android

Я не являюсь экспертом в потоках сопрограмм, поэтому мне действительно нужна помощь. У меня есть две базы данных комнат в Android, т.е. UserData и UserProfileImage.

data class UserData(
val UserName : String,
val MobileNumber : String,
val tags : List<String>)
data class UserProfileImage(
val MobileNumber : String,
val ProfileUrl : String)

я создал два запроса для получения потока из обеих таблиц, например:

@Query("SELECT * FROM users_profile")
fun getUserProfileList() : Flow<List<UserProfileImage>>

@Query("SELECT * FROM users_data")
fun getUserDataList() : Flow<List<UserData>>

моя конечная цель - собрать данные из обеих таблиц и объединить их, как CombinedData (val UserName: String, val MobileNumber: String, val tags: List, val ProfileUrl: String) на основе значения "MobileNumber" и, наконец, показать их в recyclerview . как я могу объединить функции сбора, чтобы, если какая-либо из этих таблиц наблюдает какие-либо изменения в данных, тогда объединенные данные также должны обновляться, что в конечном итоге приводит к обновлению моего recyclerview. Заранее спасибо.

я читал о flatMapMerge, flatMapConcat и т. д., но не могу полностью понять, как именно я могу их использовать.

0
0
116
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Лучшим подходом было бы избавиться от двух таблиц в первую очередь. Если у ваших пользователей есть только одно изображение, вы можете сохранить ссылку на изображение в пользовательской таблице. Если это не так, вы можете использовать оператор SQL JOIN для объединения таблиц. В этом случае ваша функция комнаты будет

@Query("SELECT * FROM UserData JOIN UserProfileImage ON UserData.MobileNumber = UserProfileImage.MobileNumber")
fun getUsersWithImages(): Flow<Map<UserData,List<UserProfileImage>>>

Это должно делать именно то, что вы хотите, без явного объединения Flows.

Однако, если вы все еще хотите сделать не в слое Room, это можно сделать следующим образом:

val usersFlow = getUserDataList()
val picturesFlow = getUserProfileList()
val mergedFlow: Flow<Map<UserData, List<UserProfileImage>>> = usersFlow.combine(picturesFlow) { users, profiles ->
   val usersProfiles = profiles.groupBy { it.MobileNumber }
   val result = buildMap {
     for (user in users) {
       put(user,usersProfiles[user.MobileNumber])
     }
   }
   result
}
Ответ принят как подходящий

Вместо того, чтобы создавать два потока и объединять их позже, вы можете создать один поток с помощью отношений ROOMDB.

data class UserDataWithProfile(
    @Embedded val userData: UserData,
    @Relation(
         parentColumn = "MobileNumber",
         entityColumn = "MobileNumber"
    )
    val profileImage: UserProfileImage
)

И когда вы хотите запросить из ROOMDB, вы можете запросить поток пользовательских данных с изображением профиля, используя один запрос -

@Transaction
@Query("SELECT * FROM users_data")
fun getUserDataProfileList(): Flow<UserDataWithProfile>

в этом случае, если мой API-интерфейс фонового сервера обновит таблицу «users_profile» последними изображениями пользователей, будет ли поток автоматически собирать новые данные, чтобы я мог обновить эти изображения в recyclerview?

Ravi.Dudi 09.04.2023 10:19

Да, в отношениях «один к одному» между двумя таблицами в базе данных Room DB любое изменение в любой из таблиц вызовет поток, который получает связанные данные.

Akash Kashyap 09.04.2023 10:50

Другие вопросы по теме