From 5d175ccfc7f8fcbf0c51f5c2c563662bbd83f7d0 Mon Sep 17 00:00:00 2001 From: yujin Date: Thu, 7 Mar 2024 14:46:33 +0900 Subject: [PATCH 1/5] feat: formattedTime --- .../unscramble/presentation/MainViewModel.kt | 9 ++++- .../presentation/play/PlayFragment.kt | 12 +++++- app/src/main/res/layout/fragment_play.xml | 37 +------------------ 3 files changed, 21 insertions(+), 37 deletions(-) diff --git a/app/src/main/java/com/yourssu/unscramble/presentation/MainViewModel.kt b/app/src/main/java/com/yourssu/unscramble/presentation/MainViewModel.kt index a138375..28b3cfe 100644 --- a/app/src/main/java/com/yourssu/unscramble/presentation/MainViewModel.kt +++ b/app/src/main/java/com/yourssu/unscramble/presentation/MainViewModel.kt @@ -20,6 +20,8 @@ class MainViewModel @Inject constructor() : ViewModel() { private val _time: MutableStateFlow = MutableStateFlow(0) val time: StateFlow = _time + private val _formattedTime: MutableStateFlow = MutableStateFlow("00:00") + val formattedTime: StateFlow = _formattedTime fun updateTime(time: Int) { _time.value = time } @@ -38,8 +40,13 @@ class MainViewModel @Inject constructor() : ViewModel() { val mHandler = Handler(Looper.getMainLooper()) mHandler.postDelayed({ // 반복실행할 구문 + val minutes = cnt / 60 + val remainingSeconds = cnt % 60 + _formattedTime.value = String.format("%02d:%02d", minutes, remainingSeconds) cnt-- - Log.d("MainViewModel", "$cnt") + + Log.d("MainViewModel", "Formatted Time: ${_formattedTime.value}") + if (cnt <= 0) { mTimer.cancel() Log.d("MainViewModel", "타이머 종료") diff --git a/app/src/main/java/com/yourssu/unscramble/presentation/play/PlayFragment.kt b/app/src/main/java/com/yourssu/unscramble/presentation/play/PlayFragment.kt index 243ae1d..5e8433d 100644 --- a/app/src/main/java/com/yourssu/unscramble/presentation/play/PlayFragment.kt +++ b/app/src/main/java/com/yourssu/unscramble/presentation/play/PlayFragment.kt @@ -1,6 +1,7 @@ package com.yourssu.unscramble.presentation.play import android.os.Bundle +import android.util.Log import android.view.LayoutInflater import android.view.View import androidx.fragment.app.activityViewModels @@ -34,15 +35,24 @@ class PlayFragment : BindFragment() { findNavController().navigate(R.id.endFragment) } - mainViewModel.startTimer() viewLifecycleOwner.lifecycleScope.launch { + + mainViewModel.startTimer() + mainViewModel.isEnd .collectLatest { isEnd -> if (isEnd) { findNavController().navigate(R.id.endFragment) } } + + mainViewModel.formattedTime + .collectLatest { formattedTime -> + Log.d("play",formattedTime) + // UI 업데이트 + binding.tvPlayTime.text = formattedTime + } } } } diff --git a/app/src/main/res/layout/fragment_play.xml b/app/src/main/res/layout/fragment_play.xml index 74a0271..7d07052 100644 --- a/app/src/main/res/layout/fragment_play.xml +++ b/app/src/main/res/layout/fragment_play.xml @@ -98,12 +98,12 @@ android:layout_marginStart="10dp" android:src="@drawable/ic_alarm" app:layout_constraintBottom_toBottomOf="parent" - app:layout_constraintEnd_toStartOf="@+id/tv_play_hour" + app:layout_constraintEnd_toStartOf="@+id/tv_play_time" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> - - Date: Thu, 7 Mar 2024 15:11:06 +0900 Subject: [PATCH 2/5] =?UTF-8?q?fix:=20scroll=20view=20=EB=B3=B5=EA=B5=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/main/res/layout/fragment_play.xml | 272 +++++++++++----------- 1 file changed, 139 insertions(+), 133 deletions(-) diff --git a/app/src/main/res/layout/fragment_play.xml b/app/src/main/res/layout/fragment_play.xml index ce0b18a..2683f3a 100644 --- a/app/src/main/res/layout/fragment_play.xml +++ b/app/src/main/res/layout/fragment_play.xml @@ -13,39 +13,38 @@ + + - - - - + - - - - - - - - - - - - + + android:layout_height="wrap_content"> - + app:layout_constraintTop_toTopOf="parent"> + + + + + + + + - + + + app:layout_constraintTop_toBottomOf="@+id/et_answer"> + + + + + + + + + + - - - From d7af13b219901d8c2861801bfce9932ce2a4f9dc Mon Sep 17 00:00:00 2001 From: yujin Date: Thu, 7 Mar 2024 15:11:21 +0900 Subject: [PATCH 3/5] feat: main viewmodel observe --- .../presentation/play/PlayFragment.kt | 41 ++++++++++--------- 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/app/src/main/java/com/yourssu/unscramble/presentation/play/PlayFragment.kt b/app/src/main/java/com/yourssu/unscramble/presentation/play/PlayFragment.kt index fc97d5c..f8df306 100644 --- a/app/src/main/java/com/yourssu/unscramble/presentation/play/PlayFragment.kt +++ b/app/src/main/java/com/yourssu/unscramble/presentation/play/PlayFragment.kt @@ -32,6 +32,7 @@ class PlayFragment : BindFragment() { binding.lifecycleOwner = viewLifecycleOwner observeViewModel() + observeMainViewModel() viewModel.checkValid() observeNavigationToEnd() setupListeners() @@ -47,6 +48,26 @@ class PlayFragment : BindFragment() { } } + private fun observeMainViewModel() { + lifecycleScope.launch { + mainViewModel.startTimer() + + mainViewModel.isEnd + .collectLatest { isEnd -> + if (isEnd) { + findNavController().navigate(R.id.endFragment) + } + } + + mainViewModel.formattedTime + .collectLatest { formattedTime -> + Log.d("play", formattedTime) + // UI 업데이트 + binding.tvPlayTime.text = formattedTime + } + } + } + private fun observeNavigationToEnd() { lifecycleScope.launch { viewModel.navigateToEnd.collect { navigateToEnd -> @@ -66,25 +87,5 @@ class PlayFragment : BindFragment() { viewModel.onPlayButtonClick() binding.etAnswer.text.clear() } - - - viewLifecycleOwner.lifecycleScope.launch { - - mainViewModel.startTimer() - - mainViewModel.isEnd - .collectLatest { isEnd -> - if (isEnd) { - findNavController().navigate(R.id.endFragment) - } - } - - mainViewModel.formattedTime - .collectLatest { formattedTime -> - Log.d("play",formattedTime) - // UI 업데이트 - binding.tvPlayTime.text = formattedTime - } - } } } From 27133a037322d23bffd77b4569c32aec9bc76941 Mon Sep 17 00:00:00 2001 From: yujin Date: Thu, 7 Mar 2024 15:35:35 +0900 Subject: [PATCH 4/5] =?UTF-8?q?feat:=20sharedflow=EB=A1=9C=20=EA=B5=90?= =?UTF-8?q?=EC=B2=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../unscramble/presentation/MainViewModel.kt | 53 ++++++++++++------- .../presentation/play/PlayFragment.kt | 4 +- app/src/main/res/layout/fragment_play.xml | 3 +- 3 files changed, 37 insertions(+), 23 deletions(-) diff --git a/app/src/main/java/com/yourssu/unscramble/presentation/MainViewModel.kt b/app/src/main/java/com/yourssu/unscramble/presentation/MainViewModel.kt index 28b3cfe..78a126b 100644 --- a/app/src/main/java/com/yourssu/unscramble/presentation/MainViewModel.kt +++ b/app/src/main/java/com/yourssu/unscramble/presentation/MainViewModel.kt @@ -5,7 +5,9 @@ import android.os.Looper import android.util.Log import androidx.lifecycle.ViewModel import dagger.hilt.android.scopes.ViewModelScoped +import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.SharedFlow import kotlinx.coroutines.flow.StateFlow import java.util.Timer import java.util.TimerTask @@ -20,8 +22,8 @@ class MainViewModel @Inject constructor() : ViewModel() { private val _time: MutableStateFlow = MutableStateFlow(0) val time: StateFlow = _time - private val _formattedTime: MutableStateFlow = MutableStateFlow("00:00") - val formattedTime: StateFlow = _formattedTime + private val _formattedTime = MutableSharedFlow() + val formattedTime: SharedFlow = _formattedTime fun updateTime(time: Int) { _time.value = time } @@ -30,6 +32,13 @@ class MainViewModel @Inject constructor() : ViewModel() { _isEnd.value = false } + suspend fun formattedTimer(cnt: Int) { + val minutes = cnt / 60 + val remainingSeconds = cnt % 60 + + _formattedTime.emit(String.format("%02d:%02d", minutes, remainingSeconds)) + } + fun startTimer() { var cnt = _time.value @@ -37,24 +46,28 @@ class MainViewModel @Inject constructor() : ViewModel() { // 반복적으로 사용할 TimerTask val mTimerTask = object : TimerTask() { override fun run() { - val mHandler = Handler(Looper.getMainLooper()) - mHandler.postDelayed({ - // 반복실행할 구문 - val minutes = cnt / 60 - val remainingSeconds = cnt % 60 - _formattedTime.value = String.format("%02d:%02d", minutes, remainingSeconds) - cnt-- - - Log.d("MainViewModel", "Formatted Time: ${_formattedTime.value}") - - if (cnt <= 0) { - mTimer.cancel() - Log.d("MainViewModel", "타이머 종료") - _isEnd.value = true - Log.d("MainViewModel", isEnd.value.toString()) - - } - }, 0) + suspend { + val mHandler = Handler(Looper.getMainLooper()) + + mHandler.postDelayed({ + suspend { + // 반복실행할 구문 + formattedTimer(cnt) + cnt-- + + Log.d("MainViewModel", "Formatted Time: ${_formattedTime}") + + if (cnt <= 0) { + mTimer.cancel() + Log.d("MainViewModel", "타이머 종료") + _isEnd.value = true + Log.d("MainViewModel", isEnd.value.toString()) + + } + } + }, 0) + } + } } mTimer.schedule(mTimerTask, 0, 1000) diff --git a/app/src/main/java/com/yourssu/unscramble/presentation/play/PlayFragment.kt b/app/src/main/java/com/yourssu/unscramble/presentation/play/PlayFragment.kt index f8df306..163a2ad 100644 --- a/app/src/main/java/com/yourssu/unscramble/presentation/play/PlayFragment.kt +++ b/app/src/main/java/com/yourssu/unscramble/presentation/play/PlayFragment.kt @@ -13,6 +13,7 @@ import com.yourssu.unscramble.databinding.FragmentPlayBinding import com.yourssu.unscramble.presentation.MainViewModel import com.yourssu.unscramble.util.base.BindFragment import dagger.hilt.android.AndroidEntryPoint +import kotlinx.coroutines.flow.buffer import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.launch @@ -60,7 +61,8 @@ class PlayFragment : BindFragment() { } mainViewModel.formattedTime - .collectLatest { formattedTime -> + .buffer() + .collect { formattedTime -> Log.d("play", formattedTime) // UI 업데이트 binding.tvPlayTime.text = formattedTime diff --git a/app/src/main/res/layout/fragment_play.xml b/app/src/main/res/layout/fragment_play.xml index 2683f3a..13837df 100644 --- a/app/src/main/res/layout/fragment_play.xml +++ b/app/src/main/res/layout/fragment_play.xml @@ -124,14 +124,13 @@ android:layout_height="wrap_content" android:layout_marginVertical="8dp" android:layout_marginStart="5dp" - android:layout_marginEnd="2dp" android:gravity="center" android:paddingVertical="4dp" android:textColor="@color/textBright" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintStart_toEndOf="@+id/iv_alarm" app:layout_constraintTop_toTopOf="parent" - app:text="@{mainViewModel.formattedTime}" + app:text="@{mainViewModel.formattedTime.toString()}" app:typo="subtitle1" /> From 6c6ca81682d4a953f1a78622802b2b67a6ad932a Mon Sep 17 00:00:00 2001 From: yujin Date: Thu, 14 Mar 2024 16:32:09 +0900 Subject: [PATCH 5/5] =?UTF-8?q?delete:=20=EC=9D=B4=EC=83=81=ED=95=9C=20sus?= =?UTF-8?q?pend=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../unscramble/presentation/MainViewModel.kt | 24 ++++++++++--------- .../presentation/play/PlayFragment.kt | 6 ++--- .../presentation/play/PlayViewModel.kt | 7 ++---- 3 files changed, 17 insertions(+), 20 deletions(-) diff --git a/app/src/main/java/com/yourssu/unscramble/presentation/MainViewModel.kt b/app/src/main/java/com/yourssu/unscramble/presentation/MainViewModel.kt index 78a126b..9e25fcb 100644 --- a/app/src/main/java/com/yourssu/unscramble/presentation/MainViewModel.kt +++ b/app/src/main/java/com/yourssu/unscramble/presentation/MainViewModel.kt @@ -4,11 +4,12 @@ import android.os.Handler import android.os.Looper import android.util.Log import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope import dagger.hilt.android.scopes.ViewModelScoped -import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.flow.SharedFlow import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.launch import java.util.Timer import java.util.TimerTask import javax.inject.Inject @@ -22,8 +23,8 @@ class MainViewModel @Inject constructor() : ViewModel() { private val _time: MutableStateFlow = MutableStateFlow(0) val time: StateFlow = _time - private val _formattedTime = MutableSharedFlow() - val formattedTime: SharedFlow = _formattedTime + private val _formattedTime = MutableStateFlow("0:0") + val formattedTime: StateFlow = _formattedTime.asStateFlow() fun updateTime(time: Int) { _time.value = time } @@ -32,11 +33,13 @@ class MainViewModel @Inject constructor() : ViewModel() { _isEnd.value = false } - suspend fun formattedTimer(cnt: Int) { + fun formattedTimer(cnt: Int) { val minutes = cnt / 60 val remainingSeconds = cnt % 60 + viewModelScope.launch { + _formattedTime.emit(String.format("%02d:%02d", minutes, remainingSeconds)) + } - _formattedTime.emit(String.format("%02d:%02d", minutes, remainingSeconds)) } fun startTimer() { @@ -46,16 +49,15 @@ class MainViewModel @Inject constructor() : ViewModel() { // 반복적으로 사용할 TimerTask val mTimerTask = object : TimerTask() { override fun run() { - suspend { val mHandler = Handler(Looper.getMainLooper()) mHandler.postDelayed({ - suspend { + // 반복실행할 구문 formattedTimer(cnt) cnt-- - Log.d("MainViewModel", "Formatted Time: ${_formattedTime}") + Log.d("MainViewModel", "Formatted Time: ${_formattedTime.value}") if (cnt <= 0) { mTimer.cancel() @@ -63,10 +65,10 @@ class MainViewModel @Inject constructor() : ViewModel() { _isEnd.value = true Log.d("MainViewModel", isEnd.value.toString()) + } - } }, 0) - } + } } diff --git a/app/src/main/java/com/yourssu/unscramble/presentation/play/PlayFragment.kt b/app/src/main/java/com/yourssu/unscramble/presentation/play/PlayFragment.kt index 163a2ad..e48ff8c 100644 --- a/app/src/main/java/com/yourssu/unscramble/presentation/play/PlayFragment.kt +++ b/app/src/main/java/com/yourssu/unscramble/presentation/play/PlayFragment.kt @@ -13,7 +13,6 @@ import com.yourssu.unscramble.databinding.FragmentPlayBinding import com.yourssu.unscramble.presentation.MainViewModel import com.yourssu.unscramble.util.base.BindFragment import dagger.hilt.android.AndroidEntryPoint -import kotlinx.coroutines.flow.buffer import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.launch @@ -61,11 +60,10 @@ class PlayFragment : BindFragment() { } mainViewModel.formattedTime - .buffer() .collect { formattedTime -> - Log.d("play", formattedTime) + Log.d("play", formattedTime) //여기 로그 안나옴 // UI 업데이트 - binding.tvPlayTime.text = formattedTime + binding.tvPlayTime.text = formattedTime.toString() } } } diff --git a/app/src/main/java/com/yourssu/unscramble/presentation/play/PlayViewModel.kt b/app/src/main/java/com/yourssu/unscramble/presentation/play/PlayViewModel.kt index 461b094..817c4b7 100644 --- a/app/src/main/java/com/yourssu/unscramble/presentation/play/PlayViewModel.kt +++ b/app/src/main/java/com/yourssu/unscramble/presentation/play/PlayViewModel.kt @@ -28,11 +28,8 @@ class PlayViewModel @Inject constructor( private val _solvedProblem: MutableStateFlow = MutableStateFlow(1) val solvedProblem: StateFlow = _solvedProblem.asStateFlow() - private val _timerHour: MutableStateFlow = MutableStateFlow("00") - val timerHour: StateFlow = _timerHour.asStateFlow() - - private val _timerMinute: MutableStateFlow = MutableStateFlow("00") - val timerMinute: StateFlow = _timerMinute.asStateFlow() + private val _formattedTime = MutableStateFlow("00:00") + val formattedTime: StateFlow = _formattedTime.asStateFlow() // 유효성 판단에 따른 버튼 활성화 관련 코드 // 사용자가 입력한 답안