Вложенное заполнение объектов с использованием потоковAndroid

Форум для тех, кто программирует под Android
Ответить
Anonymous
 Вложенное заполнение объектов с использованием потоков

Сообщение Anonymous »

У меня есть объект ActivityUiState (типа ActivityUiState), который имеет список поддействий (также типа ActivityUiState) и список голосовых заметок. Я пытаюсь заполнить ActivityUiState списком поддействий и голосовыми заметками, используя потоки. Каждое из поддействий может иметь свои собственные голосовые заметки, сохраненные в базе данных, которые я хотел бы включить в объекты поддействий при создании списка поддействий. На данный момент код успешно добавляет поддействия и голосовые заметки в ActivityUiState. Однако когда я пытаюсь добавить голосовые заметки для каждого из поддействий, весь объект ActivityUiState не обновляется никакими данными. Что я здесь делаю не так?
var subActivitiesUiState = emptyList()
activitiesRepository.getSubActivitiesPerMainActivity(id).collect { subActivities ->
for (subActivity in subActivities) {
var voiceNotesUiState = emptyList()
// This code block results in an empty activityUiState being returned
/*
voiceNotesRepository.getAllVoiceNotesPerActivity(subActivity.id).collect { voiceNotes ->
for (voiceNote in voiceNotes) {
// Append the mapped voice note to the voice notes list
voiceNotesUiState = voiceNotesUiState + VoiceNoteUiState(
id = voiceNote.id,
uri = voiceNote.uri,
duration = voiceNote.duration,
timestamp = voiceNote.timestamp,
activityId = voiceNote.activityId
)
}

subActivitiesUiState = subActivitiesUiState + ActivityUiState(
id = subActivity.id,
title = subActivity.title,
note = subActivity.note,
startTime = subActivity.startTime,
endTime = subActivity.endTime,
voiceNotesUiState = voiceNotesUiState,
mainActivityId = subActivity.mainActivityId
)
}
*/

subActivitiesUiState = subActivitiesUiState + ActivityUiState(
id = subActivity.id,
title = subActivity.title,
note = subActivity.note,
startTime = subActivity.startTime,
endTime = subActivity.endTime,
voiceNotesUiState = voiceNotesUiState,//TODO: Add the voice notes of the sub-activity
mainActivityId = subActivity.mainActivityId
)
}

activityUiState.update {
ActivityUiState(
id = activity.id,
title = activity.title,
note = activity.note,
startTime = activity.startTime,
endTime = activity.endTime,
subActivitiesUiState = subActivitiesUiState
)
}

var voiceNotesUiState = emptyList()
voiceNotesRepository.getAllVoiceNotesPerActivity(id).collect { voiceNotes ->
for (voiceNote in voiceNotes) {
// Append the mapped voice note to the voice notes list
voiceNotesUiState = voiceNotesUiState + VoiceNoteUiState(
id = voiceNote.id,
uri = voiceNote.uri,
duration = voiceNote.duration,
timestamp = voiceNote.timestamp,
activityId = voiceNote.activityId
)
}

activityUiState.update { it ->
it.copy(
voiceNotesUiState = voiceNotesUiState
)
}
}
}

ОБНОВЛЕНИЕ 25.11.2025
По предложению tyg я изменил свой код на следующее:
val selectedActivityId = MutableStateFlow(savedStateHandle.get(ACTIVITY_ID_SAVED_STATE_KEY))

val activityUiState = MutableStateFlow(ActivityUiState())
selectedActivityId.flatMapLatest { activityId ->
@OptIn(ExperimentalCoroutinesApi::class)
val activityState = selectedActivityId.flatMapLatest { activityId ->
if (activityId == null) return@flatMapLatest flowOf(ActivityUiState())

val flowOfActivity = activitiesRepository.getActivityStream(activityId)

val flowOfSubActivities = activitiesRepository.getSubActivitiesPerMainActivity(activityId).flatMapLatest { subActivities ->
val subActivitiesUiStates = subActivities.map { subActivity ->
voiceNotesRepository.getAllVoiceNotesPerActivity(subActivity.id).map { voiceNotes ->
ActivityUiState(
date = subActivity.date,
id = subActivity.id,
title = subActivity.title,
note = subActivity.note,
startTime = subActivity.startTime,
endTime = subActivity.endTime,
voiceNotesUiState = voiceNotes.map { voiceNote ->
VoiceNoteUiState(
id = voiceNote.id,
uri = voiceNote.uri,
duration = voiceNote.duration,
timestamp = voiceNote.timestamp,
activityId = subActivity.id
)
},
mainActivityId = subActivity.mainActivityId
)
}
}
combine(subActivitiesUiStates) { it -> it.toList() }
}

combine(
flowOfActivity,
flowOfSubActivities,
voiceNotesRepository.getAllVoiceNotesPerActivity(activityId)
) { activity, subActivitiesUiStates, voiceNotes ->
activity?.let {
activityUiState.update {
it.copy(
date = activity.date,
id = activity.id,
title = activity.title,
note = activity.note,
startTime = activity.startTime,
endTime = activity.endTime,
voiceNotesUiState = voiceNotes.map{ voiceNote ->
VoiceNoteUiState(
id = voiceNote.id,
uri = voiceNote.uri,
duration = voiceNote.duration,
timestamp = voiceNote.timestamp,
activityId = activity.id
)
},
subActivitiesUiState = subActivitiesUiStates
)
}

ActivityUiState(
date = activity.date,
id = activity.id,
title = activity.title,
note = activity.note,
startTime = activity.startTime,
endTime = activity.endTime,
voiceNotesUiState = voiceNotes.map{ voiceNote ->
VoiceNoteUiState(
id = voiceNote.id,
uri = voiceNote.uri,
duration = voiceNote.duration,
timestamp = voiceNote.timestamp,
activityId = activity.id
)
},
subActivitiesUiState = subActivitiesUiStates
)
} ?:run {
activityUiState.update {
ActivityUiState()
}

ActivityUiState()
}
}
}
.stateIn(
scope = viewModelScope,
started = SharingStarted.WhileSubscribed(stopTimeoutMillis = 5000L),
initialValue = ActivityUiState()
)

fun selectActivity(id: UUID?) {
selectedActivityId.value = id
}

Мне нужно, чтобы ActivityUiState имел тип MutableState, поэтому я использую ActivityState как StateFlow. Голосовые заметки последующих поддействий теперь загружены, спасибо
Не могли бы вы также помочь мне с этой небольшой проблемой: ActivityState и ActivityUiState не всегда обновляются при изменении значения selectedActivityId.
ОБНОВЛЕНИЕ 1.12.2025
Я понял, что ActivityState не обновляется, когда список поддействий пуст и все еще есть вызов для сбора голосовых заметок поддействий. Выполнение кода зависает на этой строке, что приводит к пустому состоянию ActivityState:
voiceNotesRepository.getAllVoiceNotesPerActivity(subActivity.id).map { voiceNotes ->


Подробнее здесь: https://stackoverflow.com/questions/798 ... sing-flows
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «Android»