From 159e6e197c7e7f510aec4b74de26434175190178 Mon Sep 17 00:00:00 2001 From: anastasiashchegoleva Date: Tue, 18 Mar 2025 23:27:13 +0300 Subject: [PATCH] Homework coroutines --- .../ui/login/LoginFragment.kt | 2 ++ .../ui/login/LoginViewModel.kt | 33 +++++++++++++++++-- .../ui/network/NetworkViewModel.kt | 17 +++++++++- .../ui/timer/TimerFragment.kt | 20 +++++++---- gradle/libs.versions.toml | 2 +- gradle/wrapper/gradle-wrapper.properties | 2 +- 6 files changed, 64 insertions(+), 12 deletions(-) diff --git a/app/src/main/kotlin/ru/otus/coroutineshomework/ui/login/LoginFragment.kt b/app/src/main/kotlin/ru/otus/coroutineshomework/ui/login/LoginFragment.kt index 06c3afe..a10821a 100644 --- a/app/src/main/kotlin/ru/otus/coroutineshomework/ui/login/LoginFragment.kt +++ b/app/src/main/kotlin/ru/otus/coroutineshomework/ui/login/LoginFragment.kt @@ -99,6 +99,8 @@ class LoginFragment : Fragment() { login.loginGroup.isVisible = false content.contentGroup.isVisible = false loading.loadingGroup.isVisible = true + login.login.text?.clear() + login.password.text?.clear() } private fun setupContent() { diff --git a/app/src/main/kotlin/ru/otus/coroutineshomework/ui/login/LoginViewModel.kt b/app/src/main/kotlin/ru/otus/coroutineshomework/ui/login/LoginViewModel.kt index 5fae38a..b8a2165 100644 --- a/app/src/main/kotlin/ru/otus/coroutineshomework/ui/login/LoginViewModel.kt +++ b/app/src/main/kotlin/ru/otus/coroutineshomework/ui/login/LoginViewModel.kt @@ -1,27 +1,56 @@ package ru.otus.coroutineshomework.ui.login +import android.util.Log import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext +import ru.otus.coroutineshomework.ui.login.data.Credentials class LoginViewModel : ViewModel() { private val _state = MutableLiveData(LoginViewState.Login()) val state: LiveData = _state + private val service = LoginApi() /** * Login to the network * @param name user name * @param password user password */ fun login(name: String, password: String) { - // TODO: Implement login + viewModelScope.launch { + Log.i(TAG, "Logging in $name...") + _state.value = LoginViewState.LoggingIn + try { + withContext(Dispatchers.IO) { + val loginResponse = service.login(Credentials(name, password)) + Log.i(TAG, "Successfully logged-in user with id: ${loginResponse.id}") + _state.postValue(LoginViewState.Content(loginResponse)) + } + } catch (t: Exception) { + Log.w(TAG, "Login error", t) + _state.value = LoginViewState.Login(t) + } + } } /** * Logout from the network */ fun logout() { - // TODO: Implement logout + viewModelScope.launch { + _state.value = LoginViewState.LoggingOut + withContext(Dispatchers.IO) { + service.logout() + } + _state.value = LoginViewState.Login() + } + } + companion object { + const val TAG = "LoginViewModel" } } diff --git a/app/src/main/kotlin/ru/otus/coroutineshomework/ui/network/NetworkViewModel.kt b/app/src/main/kotlin/ru/otus/coroutineshomework/ui/network/NetworkViewModel.kt index f006e03..82603eb 100644 --- a/app/src/main/kotlin/ru/otus/coroutineshomework/ui/network/NetworkViewModel.kt +++ b/app/src/main/kotlin/ru/otus/coroutineshomework/ui/network/NetworkViewModel.kt @@ -4,8 +4,12 @@ import android.util.Log import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.async +import kotlinx.coroutines.awaitAll import kotlinx.coroutines.isActive +import kotlinx.coroutines.launch import kotlinx.coroutines.withContext import kotlin.random.Random @@ -18,7 +22,18 @@ class NetworkViewModel : ViewModel() { val result: LiveData = _result fun startTest(numberOfThreads: Int) { - // TODO: Implement the logic + viewModelScope.launch { + _running.value = true + val results: MutableList = mutableListOf() + (1..numberOfThreads).map { _ -> + async { + val res = emulateBlockingNetworkRequest() + if (res.isSuccess) results.add(res.getOrDefault(0)) + } + }.awaitAll() + _running.value = false + _result.value = if (results.size > 0) results.reduce{ acc, res -> acc + res } / results.size else 0 + } } private companion object { diff --git a/app/src/main/kotlin/ru/otus/coroutineshomework/ui/timer/TimerFragment.kt b/app/src/main/kotlin/ru/otus/coroutineshomework/ui/timer/TimerFragment.kt index 1b7c0f1..bd98fd6 100644 --- a/app/src/main/kotlin/ru/otus/coroutineshomework/ui/timer/TimerFragment.kt +++ b/app/src/main/kotlin/ru/otus/coroutineshomework/ui/timer/TimerFragment.kt @@ -8,13 +8,14 @@ import androidx.fragment.app.Fragment import androidx.lifecycle.lifecycleScope import kotlinx.coroutines.Job import kotlinx.coroutines.delay -import kotlinx.coroutines.isActive import kotlinx.coroutines.launch import ru.otus.coroutineshomework.databinding.FragmentTimerBinding import java.util.Locale import kotlin.properties.Delegates import kotlin.time.Duration import kotlin.time.Duration.Companion.milliseconds +import kotlin.time.DurationUnit +import kotlin.time.toDuration class TimerFragment : Fragment() { @@ -24,7 +25,7 @@ class TimerFragment : Fragment() { private var time: Duration by Delegates.observable(Duration.ZERO) { _, _, newValue -> binding.time.text = newValue.toDisplayString() } - + private var job: Job = Job() private var started by Delegates.observable(false) { _, _, newValue -> setButtonsState(newValue) if (newValue) { @@ -75,11 +76,16 @@ class TimerFragment : Fragment() { } private fun startTimer() { - // TODO: Start timer + job = viewLifecycleOwner.lifecycleScope.launch { + while (true) { + time = time.plus(1L.toDuration(DurationUnit.MILLISECONDS)) + delay(1L) + } + } } private fun stopTimer() { - // TODO: Stop timer + job.cancel() } override fun onDestroyView() { @@ -94,9 +100,9 @@ class TimerFragment : Fragment() { private fun Duration.toDisplayString(): String = String.format( Locale.getDefault(), "%02d:%02d.%03d", - this.inWholeMinutes.toInt(), - this.inWholeSeconds.toInt(), - this.inWholeMilliseconds.toInt() + this.inWholeMinutes.toInt() % 60, + this.inWholeSeconds.toInt() % 60, + this.inWholeMilliseconds.toInt() % 1000 ) } } \ No newline at end of file diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 866702f..a04091b 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,5 +1,5 @@ [versions] -agp = "8.7.3" +agp = "8.8.0" kotlin = "2.1.0" coreKtx = "1.15.0" junit = "4.13.2" diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index f469e3b..b00d4e4 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ #Tue Jan 07 11:05:09 CET 2025 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists