Skip to content

Commit

Permalink
Convert LogsViewModel.logs to SharedFlow
Browse files Browse the repository at this point in the history
In order to address performance concerns over recreating lists.
  • Loading branch information
Doomsdayrs committed Feb 15, 2024
1 parent 50e6648 commit 5dcc124
Show file tree
Hide file tree
Showing 3 changed files with 10 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ class LogsFragment : TwoPaneDetailFragment(R.layout.fragment_logs) {
}

private fun onClickShare() = viewLifecycleScope.launch {
val logText = viewModel.logs.value.format()
val logText = viewModel.logs.replayCache[0].format()
val logTimestamp = LocalDateTime.now().toString()
val logTitle = "${BuildConfig.APPLICATION_ID}_${BuildConfig.VERSION_NAME}_$logTimestamp.log"

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ import androidx.lifecycle.ViewModel
import de.westnordost.streetcomplete.data.logs.LogMessage
import de.westnordost.streetcomplete.data.logs.LogsFilters
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.SharedFlow

abstract class LogsViewModel : ViewModel() {
abstract val filters: MutableStateFlow<LogsFilters>
abstract val logs: StateFlow<List<LogMessage>>
abstract val logs: SharedFlow<List<LogMessage>>
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,15 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharedFlow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.callbackFlow
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.flow.shareIn
import kotlinx.coroutines.flow.transformLatest
import kotlinx.coroutines.plus
import kotlinx.datetime.LocalDateTime
import kotlinx.datetime.LocalTime
import java.util.concurrent.CopyOnWriteArrayList

class LogsViewModelImpl(
private val logsController: LogsController,
Expand Down Expand Up @@ -55,21 +56,21 @@ class LogsViewModelImpl(
}

@OptIn(ExperimentalCoroutinesApi::class)
override val logs: StateFlow<List<LogMessage>> =
override val logs: SharedFlow<List<LogMessage>> =
filters.transformLatest { filters ->
// get prior logs into a backing state
// There will be duplication regardless.
var logs: List<LogMessage> = logsController.getLogs(filters)
val logs = CopyOnWriteArrayList(logsController.getLogs(filters))

// emit the logs for the first view
emit(logs)

// start listening to new logs
getIncomingLogs(filters).collect {
logs = logs + it
logs.add(it)
emit(logs)
}
}.stateIn(viewModelScope + Dispatchers.IO, SharingStarted.Eagerly, emptyList())
}.shareIn(viewModelScope + Dispatchers.IO, SharingStarted.Eagerly, 1)
}

private fun LogsController.getLogs(filters: LogsFilters) =
Expand Down

1 comment on commit 5dcc124

@westnordost
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, good to know that shareIn exists. Thanks!

Please sign in to comment.