MainViewModel: avoid running IO operations on the main thread
This commit is contained in:
@@ -20,6 +20,7 @@ import androidx.lifecycle.ViewModel
|
|||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
import kotlinx.collections.immutable.persistentListOf
|
import kotlinx.collections.immutable.persistentListOf
|
||||||
import kotlinx.collections.immutable.toImmutableList
|
import kotlinx.collections.immutable.toImmutableList
|
||||||
|
import kotlinx.coroutines.asCoroutineDispatcher
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import kotlinx.coroutines.flow.SharingStarted
|
import kotlinx.coroutines.flow.SharingStarted
|
||||||
import kotlinx.coroutines.flow.StateFlow
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
@@ -27,6 +28,7 @@ import kotlinx.coroutines.flow.map
|
|||||||
import kotlinx.coroutines.flow.stateIn
|
import kotlinx.coroutines.flow.stateIn
|
||||||
import kotlinx.coroutines.flow.update
|
import kotlinx.coroutines.flow.update
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
import org.fairscan.app.data.ImageRepository
|
import org.fairscan.app.data.ImageRepository
|
||||||
import org.fairscan.app.domain.CapturedPage
|
import org.fairscan.app.domain.CapturedPage
|
||||||
import org.fairscan.app.domain.PageViewKey
|
import org.fairscan.app.domain.PageViewKey
|
||||||
@@ -37,9 +39,13 @@ import org.fairscan.imageprocessing.encodeJpeg
|
|||||||
import org.opencv.android.Utils
|
import org.opencv.android.Utils
|
||||||
import org.opencv.core.Mat
|
import org.opencv.core.Mat
|
||||||
import org.opencv.imgproc.Imgproc
|
import org.opencv.imgproc.Imgproc
|
||||||
|
import java.util.concurrent.Executors
|
||||||
|
|
||||||
class MainViewModel(val imageRepository: ImageRepository, launchMode: LaunchMode): ViewModel() {
|
class MainViewModel(val imageRepository: ImageRepository, launchMode: LaunchMode): ViewModel() {
|
||||||
|
|
||||||
|
// TODO ImageRepository should be made thread-safe
|
||||||
|
private val repositoryDispatcher = Executors.newSingleThreadExecutor().asCoroutineDispatcher()
|
||||||
|
|
||||||
private val _navigationState = MutableStateFlow(NavigationState.initial(launchMode))
|
private val _navigationState = MutableStateFlow(NavigationState.initial(launchMode))
|
||||||
val currentScreen: StateFlow<Screen> = _navigationState.map { it.current }
|
val currentScreen: StateFlow<Screen> = _navigationState.map { it.current }
|
||||||
.stateIn(viewModelScope, SharingStarted.Eagerly, _navigationState.value.current)
|
.stateIn(viewModelScope, SharingStarted.Eagerly, _navigationState.value.current)
|
||||||
@@ -70,31 +76,42 @@ class MainViewModel(val imageRepository: ImageRepository, launchMode: LaunchMode
|
|||||||
|
|
||||||
fun rotateImage(id: String, clockwise: Boolean) {
|
fun rotateImage(id: String, clockwise: Boolean) {
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
|
val pages = withContext(repositoryDispatcher) {
|
||||||
imageRepository.rotate(id, clockwise)
|
imageRepository.rotate(id, clockwise)
|
||||||
_pages.value = imageRepository.pages()
|
imageRepository.pages()
|
||||||
|
}
|
||||||
|
_pages.value = pages
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun movePage(id: String, newIndex: Int) {
|
fun movePage(id: String, newIndex: Int) {
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
|
val pages = withContext(repositoryDispatcher) {
|
||||||
imageRepository.movePage(id, newIndex)
|
imageRepository.movePage(id, newIndex)
|
||||||
_pages.value = imageRepository.pages()
|
imageRepository.pages()
|
||||||
|
}
|
||||||
|
_pages.value = pages
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun deletePage(id: String) {
|
fun deletePage(id: String) {
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
|
val pages = withContext(repositoryDispatcher) {
|
||||||
imageRepository.delete(id)
|
imageRepository.delete(id)
|
||||||
_pages.value = imageRepository.pages()
|
imageRepository.pages()
|
||||||
|
}
|
||||||
|
_pages.value = pages
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun startNewDocument() {
|
fun startNewDocument() {
|
||||||
_pages.value = persistentListOf()
|
_pages.value = persistentListOf()
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
|
withContext(repositoryDispatcher) {
|
||||||
imageRepository.clear()
|
imageRepository.clear()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun getBitmap(key: PageViewKey): Bitmap? {
|
fun getBitmap(key: PageViewKey): Bitmap? {
|
||||||
val bytes = imageRepository.jpegBytes(key)
|
val bytes = imageRepository.jpegBytes(key)
|
||||||
@@ -108,12 +125,15 @@ class MainViewModel(val imageRepository: ImageRepository, launchMode: LaunchMode
|
|||||||
|
|
||||||
fun handleImageCaptured(capturedPage: CapturedPage) {
|
fun handleImageCaptured(capturedPage: CapturedPage) {
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
|
val pages = withContext(repositoryDispatcher) {
|
||||||
imageRepository.add(
|
imageRepository.add(
|
||||||
capturedPage.pageJpeg,
|
capturedPage.pageJpeg,
|
||||||
compressJpeg(capturedPage.source, 90),
|
compressJpeg(capturedPage.source, 90),
|
||||||
capturedPage.metadata,
|
capturedPage.metadata,
|
||||||
)
|
)
|
||||||
_pages.value = imageRepository.pages()
|
imageRepository.pages()
|
||||||
|
}
|
||||||
|
_pages.value = pages
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user