Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ViewModels (a start) #5482

Merged
merged 21 commits into from
Mar 8, 2024
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Revert "solve performance issue in LogsViewModel (?)"
This reverts commit 314f05f.
  • Loading branch information
westnordost committed Feb 12, 2024

Verified

This commit was signed with the committer’s verified signature.
lkysow Luke Kysow
commit 45b225966fcbb8df180e874c7cd0bd60e85cb5a5
Original file line number Diff line number Diff line change
@@ -8,6 +8,7 @@ import androidx.recyclerview.widget.DividerItemDecoration
import de.westnordost.streetcomplete.BuildConfig
import de.westnordost.streetcomplete.R
import de.westnordost.streetcomplete.data.logs.LogMessage
import de.westnordost.streetcomplete.data.logs.format
import de.westnordost.streetcomplete.databinding.FragmentLogsBinding
import de.westnordost.streetcomplete.screens.TwoPaneDetailFragment
import de.westnordost.streetcomplete.util.ktx.now
@@ -61,11 +62,12 @@ class LogsFragment : TwoPaneDetailFragment(R.layout.fragment_logs) {
}

private fun onClickShare() = viewLifecycleScope.launch {
val logText = viewModel.logs.value.format()
val logTimestamp = LocalDateTime.now().toString()
val logTitle = "${BuildConfig.APPLICATION_ID}_${BuildConfig.VERSION_NAME}_$logTimestamp.log"
westnordost marked this conversation as resolved.
Show resolved Hide resolved

val shareIntent = Intent(Intent.ACTION_SEND).also {
it.putExtra(Intent.EXTRA_TEXT, viewModel.logsText)
it.putExtra(Intent.EXTRA_TEXT, logText)
it.putExtra(Intent.EXTRA_TITLE, logTitle)
it.type = "text/plain"
}
Original file line number Diff line number Diff line change
@@ -4,12 +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.SharedFlow
import kotlinx.coroutines.flow.StateFlow

abstract class LogsViewModel : ViewModel() {
abstract val filters: MutableStateFlow<LogsFilters>
westnordost marked this conversation as resolved.
Show resolved Hide resolved
abstract val logs: SharedFlow<List<LogMessage>>

abstract val logsText: String
abstract val logs: StateFlow<List<LogMessage>>
}
Original file line number Diff line number Diff line change
@@ -4,13 +4,13 @@ import androidx.lifecycle.viewModelScope
import de.westnordost.streetcomplete.data.logs.LogMessage
import de.westnordost.streetcomplete.data.logs.LogsController
import de.westnordost.streetcomplete.data.logs.LogsFilters
import de.westnordost.streetcomplete.data.logs.format
import de.westnordost.streetcomplete.util.ktx.systemTimeNow
import de.westnordost.streetcomplete.util.ktx.toEpochMilli
import de.westnordost.streetcomplete.util.ktx.toLocalDate
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.getAndUpdate
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import kotlinx.datetime.LocalDateTime
@@ -23,40 +23,28 @@ class LogsViewModelImpl(
private val logsControllerListener = object : LogsController.Listener {
override fun onAdded(message: LogMessage) {
if (filters.value.matches(message)) {
synchronized(_logs) {
_logs.add(message)
logs.tryEmit(_logs)
}
// TODO this is hugely inefficient (log list is copied every time a single entry is added!!!)
logs.update { it + message }
westnordost marked this conversation as resolved.
Show resolved Hide resolved
}
}
}

override val filters: MutableStateFlow<LogsFilters>

override val logs: MutableSharedFlow<List<LogMessage>> = MutableSharedFlow(1)
private val _logs = ArrayList<LogMessage>()

override val logsText: String get() = _logs.format()
override val logs: MutableStateFlow<List<LogMessage>> = MutableStateFlow(emptyList())

init {
val startOfToday = LocalDateTime(systemTimeNow().toLocalDate(), LocalTime(0, 0, 0))
filters = MutableStateFlow(LogsFilters(timestampNewerThan = startOfToday))
viewModelScope.launch {
// get logs initially, subscribe to updates and then...
updateLogs(filters.value)
// get logs initially and subscribe to updates, then
logs.value = withContext(Dispatchers.IO) { logsController.getLogs(filters.value) }
logsController.addListener(logsControllerListener)

// get logs anew whenever filters changed
filters.collect { f -> updateLogs(f) }
}
}

private suspend fun updateLogs(filters: LogsFilters) {
val newLogs = withContext(Dispatchers.IO) { logsController.getLogs(filters) }
synchronized(_logs) {
_logs.clear()
_logs.addAll(newLogs)
logs.tryEmit(_logs)
filters.collect { f ->
logs.update { withContext(Dispatchers.IO) { logsController.getLogs(f) } }
}
}
}