본문 바로가기

Android

(26)
Build Logic 모듈에는 build.gradle이라는 파일이 포함되어 있다.멀티 모듈을 사용하기 위해 모듈을 생성하면 따로 추가하지 않아도 build.gradle 파일이 포함되어 생성되며, 추가 된 모듈은 settings.gradle 파일에 include: 모듈 형식으로 자동으로 추가된다.Gradle - Groovy 언어를 기반으로 한 오픈소스 빌드 도구 빌드도구 - 애플리케이션 생성을 자동화 하기 위한 프로그램 빌드 과정을 간단히 요약하자면 다음과 같다.settings.gradle이 먼저 실행되고, 정의 된 각각의 모듈에 대한 Project 인스턴스를 생성한다.이후 각 모듈의 Project 인스턴스를 통해 빌드 설정을 진행하게 되는데, Project 인스턴스를 사용하는 부분이 바로 모듈 내에 있는 build.gradl..
멀티 모듈 모든 클래스는 각자의 역할이 뚜렷하게 존재한다.대표적인 예로 ViewModel은 UI의 상태를 관리하기 위한 클래스로, UI 상태를 제외한 나머지는 알 필요가 없다. 그러나 데이터베이스에서 데이터를 가져오기 위해 Repository를 사용해야 하기 때문에 추상화 된 Repository를 DI를 통해 주입받아 사용하곤 한다.이처럼 각자의 역할을 정의하고 이를 의존성 주입을 통해 관리하게 되는데, 하나의 모듈에서 프로젝트를 구현하다 보면 본인도 모르는 사이에 각 코드간의 의존성이 높아지고, 나중에는 클래스마다 복잡한 관계를 갖게 되는 경우가 생기게 된다. 1. 멀티 모듈멀티 모듈을 사용하면 위와 같은 문제를 어느 정도 개선할 수 있다.역할 및 기능 별로 모듈을 생성, 관심사 분리를 통해 유지보수 및 재사용성..
[EditText] 날짜 입력하기 with Flow 개인 프로젝트에서 날짜를 입력하는 화면이 있다.조건시작일은 필수로 입력해야 하며, 종료일은 선택할 수 있다.EditText가 형식에 맞게 채워지면 초록색 테두리로 변한다.화면에 주어진 EditText가 모두 YYYY-MM-DD 형식으로 채워져야 등록버튼이 활성화된다.날짜 범위가 올바르지 않다면 Toast Massage 알림 상태 정의class DateViewModel: ViewModel() { private val _startDate = MutableStateFlow("") val startDate = _startDate.asStateFlow() private val _endDate = MutableStateFlow("") val endDate = _endDate.asStateFlo..
AppWidget - View 구성 요소Widget LayoutAppWidgetProviderInfoAppWidgetProviderRemoteViewsWidget LayoutWidget은 기본적으로 RemoteViews를 사용한다.RemoteViews에 사용할 수 있는 View는 제한적인데, 종류는 다음과 같다.이를 이용하여 아래와 같은 간단한 위젯을 만들 수 있다. RemoteViews에 사용할 수 있는 View와 Layout을 사용하여 자유롭게 Widget을 디자인 할 수 있지만, Widget의 크기를 고려하여 구현해야 한다. AppWidgetProviderInfoAppWidgetProviderInfo는 Widget의 필수 속성들을 정의하며, XML로 구현할 수 있다.(해당 파일의 경로는 res/xml/ 에 저장한다.) ..
Navigation Component 기존에 Fragment를 사용하기 위해선 FragmentManager를 사용하여 Fragment에 필요한 작업들을 수동적으로 처리해줘야 했다.fragmentManager = supportFragmentManagerval transaction = fragmentManager .beginTransaction() .addToBackStack(name)transaction.replace(R.id.nav_host_fragment_content_main, fragment).commit() Jetpack의 Navigation Component는 이러한 부분들을 좀 더 쉽고 간편하고 직관적으로 사용 할 수 있도록 도와주는 라이브러리이다. 구성 요소Na..
[DataBinding] BindingAdapter 함수 파라미터 전달 프로젝트 리팩토링을 진행하던 도중 Tab을 구현할 일이 생겼는데, MVVM을 사용하고 있었기에 Tab 관련 설정을 BindingAdapter를 통해 구현하고자 했다. 관련하여 addTabSelectedListener를 설정하기 위해 BindingAdapter 파라미터로 함수를 전달하려 했지만 다음과 같은 오류를 만났다. object TabBindingAdapter { @JvmStatic @BindingAdapter("app:tab_selected") fun tabSelectedListener(tabLayout: TabLayout, changedTab: (StatisticsTab) -> Unit){ tabLayout.addOnTabSelectedListener(object : ..
Compose 프로젝트 일부 MVI로 마이그레이션 지금까지 MVI를 간단한 스톱워치로 알아봤는데, 스톱워치 기능 자체가 간단하다보니 MVI의 장점을 크게 느끼지 못했다. 전에 팀 프로젝트로 진행했던 Compose 프로젝트 일부를 Orbit 라이브러리를 이용하여 MVI를 적용해보고, 전과 후를 비교하여 어떤 차이가 있는지 확인해보고자 했다. MVI를 적용할 부분은 SavePhotoScreen으로, 사진을 찍고 추가적인 정보(라벨, 설명 등)를 입력 후 저장하는 기능을 담당한다.https://github.com/boostcampwm-2024/and04-Nature-Album/blob/dev/app/src/main/java/com/and04/naturealbum/ui/add/savephoto/SavePhotoScreen.kt and04-Nature-Album..
MVI 라이브러리 - Orbit with Compose MVI 첫 포스팅에서는 라이브러리 없이 MVI 패턴을 구현해보았다.https://snaildeveloper.tistory.com/140 MVI 패턴스톱워치는 시간과 시작/종료 버튼, 리셋 버튼이 있다.사용자가 시작 버튼을 누르면 시간이 올라가며, 종료 버튼을 누르면 시간이 멈추게 되고, 리셋 버튼을 누른다면 시간이 0으로 초기화 된다.snaildeveloper.tistory.com Orbit 라이브러리를 사용하면 보다 쉽게 MVI 패턴을 구현할 수 있다.https://github.com/orbit-mvi/orbit-mvi GitHub - orbit-mvi/orbit-mvi: A simple MVI framework for Kotlin Multiplatform and AndroidA simple MVI f..
MVI 패턴 스톱워치는 시간과 시작/종료 버튼, 리셋 버튼이 있다.사용자가 시작 버튼을 누르면 시간이 올라가며, 종료 버튼을 누르면 시간이 멈추게 되고, 리셋 버튼을 누른다면 시간이 0으로 초기화 된다. 1. 사용자가 버튼을 클릭함으로써 이벤트가 발생2. 이벤트마다 시간이 흘러가거나, 멈추거나, 초기화가 되는 상태가 생성3. 이 상태를 View에 알려줘 사용자는 스톱워치의 기능을 사용할 수 있게 된다. MVI의 기본 구조는 발생하는 이벤트를 가지고 상태를 관리하고 상태에 따라 UI를 단방향으로 처리하는 것이다.Model : Intent로 부터 전달 받은 이벤트를 처리하여 만든 상태를 View에게 전달View : Model에서 전달 받은 상태를 UI에 적용Intent : View에서 발생한 사용자의 액션, 동작을 Mo..
[Compose] Composable 함수의 데이터 관리 Compose는 Composable 함수를 기반으로 UI를 구성한다. UI를 구성하는 과정에서 다양한 데이터를 저장하고 사용하지만, Composable 함수의 특성 상 기존처럼 변수를 선언한다면 원하는 결과 값을 얻을 수 없다. Recomposition이 일어나면 해당 Composable 함수를 다시 재실행하여 기존의 데이터가 다 초기화되기 때문이다.또한 UI와 직접적으로 연관이 있는 데이터의 경우 값이 변경됨에 따라 Recomposition이 일어나야 하지만 기존의 변수를 사용한다면 값의 변경을 알아차릴 수 없기 때문에 Recomposition 자체가 일어나지 않는다. 그렇다면 Composable 함수에서는 데이터를 어떻게 선언해야 할까?StateComposable 함수가 Recomposition이 되..