미라클 모닝을 비롯해서 동기부여를 도와주는 자기계발 모바일 앱 서비스입니다.
- 직접 취업 준비를 하면서 동기부여에 도움을 줄 수 있는 앱이 있으면 어떨까 생각했습니다.
- MVVM 패턴을 학습하고 싶었습니다.
- learning by doing 방식으로 보다 재밌게 학습하고 싶었습니다.
- 혼자서 맨땅에 헤딩해보고 싶었습니다.
✔ 미라클 모닝: 일어난 시간을 달력에 스탬프처럼 기록할 수 있습니다.
✔ 동기부여: 유튜브의 동기부여 영상들을 주제별로 분류해서 보여줍니다.
✔ Todo 리스트: 오늘 할 일을 기록하고 관리합니다.
1. 미라클 모닝 | 2. 동기부여 |
---|---|
![]() |
![]() |
애니메이션 | 추가 | 변경(button, swipe) |
---|---|---|
![]() |
![]() |
![]() |
변경(drag&drop) | 삭제&되돌리기(button, swipe) | 상태 유지(Room) |
---|---|---|
![]() |
![]() |
![]() |
AAC를 활용, MVVM 패턴 적용, 커스텀 캘린더, 야간 모드 지원, 리팩토링
개인 프로젝트
- 미라클 모닝: 2022-01-27 ~ 2022-02-18 (기획, 구현, UI, 리팩토링)
- 동기 부여: 2022-03-02 ~ 2022-03-06 (기획, 데이터 수집/분류, 구현, UI)
- Todo 리스트: 2022-04-25 ~ 2022-06-06
Kotlin, MVVM, Databinding, (Shared)ViewModel, LiveData, Coroutine, Room, ListAdapter
자세히
CalendarViewModel.kt - 캘린더를 보여주는 프래그먼트의 뷰모델
init {
setUpMiracleDateList()
}
private fun setUpMiracleDateList() {
// ...
// 일어난 시간을 담고 있는 스탬프 객체들을 Room에서 가져온다
viewModelScope.launch {
loadStamps()
_isStampLoaded.value = true // 스탬프 로딩 완료
}
}
- suspend 함수를 사용해서 스탬프 로딩을 끝마쳤을 때 데이터를 갱신합니다.
private suspend fun loadStamps() {
// ...
// 코루틴스코프로 하위 코루틴이 모두 끝나야 suspend 함수가 종료되도록 함
coroutineScope {
launch { loadPrevMonthTailStamps(prevStartDay, prevEndDay) }
launch { loadCurrentMonthStamps() }
launch { loadNextMonthHeadStamps(nextEndDay) }
}
}
- coroutineScope를 사용해서 하위 코루틴들이 데이터 로딩을 모두 마치면 suspend 함수를 종료시킵니다.
private suspend fun loadCurrentMonthStamps() {
val stamps = calendarRepository.getMonthStamps(currentDateTime.millis)
stamps.forEach { stamp ->
val pos = baseCalendar.prevMonthTailOffset + stamp.dayOfMonth - 1
miracleDateList[pos].wakeUpMinutes.value = stamp.wakeUpMinutes
}
}
private val coroutineScope: CoroutineScope = CoroutineScope(Dispatchers.IO)
suspend fun getMonthStamps(monthMillis: Long): List<MiracleStamp> {
return withContext(coroutineScope.coroutineContext) {
return@withContext calendarDao.getMonthStamps(monthMillis)
}
}
- withContext를 사용해서 IO로 컨텍스트를 변경하고 작업 결과를 반환합니다.
자세히
- 문제 상황
전체 화면 모드에서 회전되었던 화면 방향이 전체 화면을 해제했을 때 되돌아오지 않음 - 해결 방법
- YouTubePlayer에 있는 fullScreenListener를 추가해서 전체 화면 여부에 따라 Activity.requestedOrientation을 변경
player.setOnFullscreenListener { requestedOrientation = if (it) { ActivityInfo.SCREEN_ORIENTATION_LOCKED } else { ActivityInfo.SCREEN_ORIENTATION_USER } isPlayerFullScreen = it }
- isPlayerFullScreen: Boolean 변수를 선언해서 백버튼을 클릭했을 때 전체 화면 모드를 해제하고 화면 방향을 유저가 설정한 방향으로 세팅
override fun onBackPressed() { if (isPlayerFullScreen && youtubePlayer != null) { requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_USER youtubePlayer!!.setFullscreen(false) } else{ super.onBackPressed() } }