프로그래밍/Android 136

ManifestPlaceholder : 매니페스트에서 빌드 변수 사용하기

카카오 SDK 연동을 하다보면 AndroidManifest에 APP KEY를 요구하는데, 중요한 Api Key를 보관할때 properties 파일을 별도로 만들어두고 빌드시에 BuildConfig에 변수를 할당하여 사용하는 패턴이 일반적이다. 하지만 AndroidManifest에서 BuildConifg에 접근하는 방법은 없다. 이때 사용하는 것이 바로 ManifestPlaceholder다. 위 Manifest 내용은 카카오 SDK 예시인데, 저렇게 NATIVE_APP_KEY를 가져올 수 있도록 세팅해보자. 안드로이드 프로젝트를 만들면 기본적으로 생성되는 local.properties를 사용해보도록 하겠다. kakao.native_app_key 프로퍼티를 추가해준다....kakao.native_app_ke..

Android Room은 어떻게 Flow를 지원할 수 있었을까?

Room의 room-ktx 종속항목을 추가하면 Kotlin Extension과 Coroutine 지원을 받을 수 있게 된다. 이는 가져다쓰는 개발자 입장에서도 굉장히 편리해지는데, 그중에서도 Flow의 지원은 DB내의 데이터가 바뀔때마다 쿼리를 실행해서 결과값을 방출 할 수 있도록 해준다.implementation "androidx.room:room-ktx:$room_version" 데이터의 변화가 일어났을때 이를 감지해서 새로운 Flow를 방출하는 구조를 짜고싶었는데, 문득 Room이 생각나서 내부 구현을 찾아보게 되었다.@JvmStatic public fun createFlow( db: RoomDatabase, inTransaction: Boolean, tableName..

Mastering Android ViewModels: init {} 블록에서 상태를 초기화하는 것을 피하라

ViewModel의 init {} 블록에서 상태를 초기화하는 것은 편리해보인다.나도 프로젝트에서 종종 그렇게 해 오고는 했는데, 그렇게 하지말라는 이유는 다음과 같다. 1. ViewModel 생성과 강하게 커플링됨데이터를 가져오는 타이밍이 ViewModel 생성시에 있기 때문에, 새로고침 등 사용자 상호작용이나 기타 이벤트에 따라 데이터 로딩시점을 제어하기 어렵게 만든다.  2. 테스트하기 어려움ViewModel이 생성되자마자 데이터 로드가 시작되므로 1번의 이유로 인해 테스트하기 어려워진다.  3. 리소스 낭비의 가능성앱이나 화면에 진입하자마자 데이터를 필요로 하지 않을 경우, 자원의 비효율적인 사용으로 이어질 수 있음. 4. UI 응답성init {} 블록은 최대한 가볍게 유지해야한다. 여기에서 메인 ..

Mastring Android ViewModels: 필요하다면, 생성자에 의존성을 Lazy하게 주입하라

ViewModel의 생성자에 있는 모든 의존성들을 Lazy Inject하라는 것은 아니지만, 드물게 사용하는 것들은 Lazy로 바꿈으로서 초기화 성능을 개선할 수 있다. 의존성이 실제로 필요할때만 주입되므로 이로인한 이점은 다음과 같다. 1. 빠른 시작2. 더 낮은 메모리 점유율3. CPU 부하 감소 Lazy Initialization을 사용해야하는 경우- 규모가 큰 의존성- 드물게 사용되는 의존성- 조건부 의존성 케이스 스터디@HiltViewModelclass BookViewModel @Inject constructor( @IoDispatcher private val ioDispatcher: CoroutineDispatcher, private val bookmarkUseCase: dagger..

[안드로이드] MyMavenRepo로 Private Repository 라이브러리 무료 배포하기

Jitpack에서 MyMavenRepo로...안드로이드 SDK 프로토 타입을 개발중인데, 개발한 SDK를 프로덕트에 붙이려니 aar 파일로 직접 배포하는 방식은 아무래도 귀찮았다. 처음엔 자료가 많은 jitpack으로 시작을 했었는데 jitpack은 Private Repository에 대해서는 요금을 부과한다. 무료체험이 끝나니 최소 월 $12를 지불해야했다. 회사에 청구할까 고민했지만 이런 문제를 해결하는 것도 재미있겠다 싶어서 짧게 서치하니 MyMavenRepo라는 무료 플랜이있는 MavenRepository를 발견했다. Step 1. 가입하고 인증하기 먼저 Register를 눌러 유효한 이메일 주소와 MyMavenRepo에서 사용할 Password를 입력해서 가입한다.비밀번호 확인? ..

Coil 인터셉터를 활용한 이미지 로딩 최적화 방법

Coil의 이미지 파이프라인은 아래 5가지의 메인 파트로 이루어져 있는데, Interceptor는 그 중 첫번째로 실행되는 녀석이다. Interceptor -> Mapper > Keyer -> Fetcher -> Decoder 커스텀 Interceptor를 이용하면 일종의 캐시 레이어(Cache Layer)를 만들 수 있다. 요청을 가로채서 요청 파라미터를 수정하거나...HTTP Request를 했지만 휴대폰 내에 파일이 있다면 File로 돌려버리거나 말이다. 또, 앱에서 정의한 커스텀 스키마로 이미지를 불러오는 것도 가능해진다. 어찌되었건 지금 간단히 예시로 볼 것은 Unsplash 이미지를 불러올때 이미지 사이즈를 최적화 시켜주는 Interceptor다. (Github에 많이 떠돌아다니는 코드다 ㅋㅋ..

[Hilt] Custom Component의 활용 - 지역별 DB 생성하기

Hilt의 Component와 Scope Hilt에서는 안드로이드 앱의 다양한 생명주기에 맞는 미리 정의된 컴포넌트 들을 제공한다. 컴포넌트 위의 어노테이션은 해당 컴포넌트의 수명에 대한 바인딩 범위를 지정한다. 이렇게 어노테이션을 붙이면 해당 컴포넌트와 오브젝트는 생명주기를 같이하게 된다. 바인딩은 Scoped와 Unscoped 두 가지 유형으로 나누어지는데, 기본적으로는 Unscoped 바인딩이다. Unscoped: 해당 바인딩이 요청될 때마다 새로운 인스턴스가 생성됨 Scoped: 범위가 지정된 컴포넌트의 인스턴스 당 한 번만 생성되며, 해당 바인딩에 대한 모든 요청은 동일한 인스턴스를 공유함 @Module @InstallIn(FragmentComponent::class) object FooModu..

[Jetpack Compose] @Immutable과 @Stable이란

Stable과 Unstable Recomposition이 일어날때, Compose는 Stable과 Unstable로 유형을 구분한다. - Stable: 불변하는 것(Immutable), 혹은 Recomposition간에 값이 변경되었는지 여부를 추적할 수 있는 경우. - Unstable: Recomposition간에 값이 변경되었는지 알 수 없는 경우. 만약에 어떤 타입이 Stable하다면 Skip할 수 있지만 Unstable하다면 다시 그려야하므로, Stable과 Unstable하다는 것은 Compose에게 아주 중요하고 이것은 결국 성능에까지도 영향을 미치게 된다. 따라서 가능한한 클래스를 Immtable하게 만든다면 성능에 조금이나마 도움이 될 것이다. @Immutable @Immutable은 컴포..

Mainframer - 리모트 서버에서 빌드를 돌려보자

안드로이드 프로젝트 빌드 시간으로 고민하는 사람들이 많을 거라고 생각한다. 좋은 장비가 도움을 줄수는 있지만, 남아도는 좋은 서버가 있다면? (꽤 희망적인 가정인데) Mainframer나 Mirakle을 이용하면 SSH를 통해 리모트 머신에서 프로젝트를 빌드하고 결과를 로컬에 동기화 할 수 있다. 이것이 가능한데에는 rsync가 큰 역할을 한다. 우선 빌드서버와 SSH 연결이 가능한 상태를 가정하도록 하겠다. SSH 연결만 된다면 리모트 머신에서 딱히 준비할 건 없기때문이다. Mainframer Releases 페이지에서 최신 버전의 mainframer.sh를 다운받는다. . └── MyAndroidProject/ ├── app ├── .mainframer/ │ ├── config │ ├── ignore..

[안드로이드] plugin 적용 중 오류 해결방법: The request for this plugin could not be satisfied because the plugin is already on the classpath with an unknown version

오류발생 The request for this plugin could not be satisfied because the plugin is already on the classpath with an unknown version version catalog를 이용한 plugin 적용중에 "The request for this plugin could not be satisfied because the plugin is already on the classpath with an unknown version"라는 오류가 떴다. 당시 나의 plugins 블록은 다음과 같다. kapt를 추가하면서 문제가 발생했다. plugins { alias(libs.plugins.kotlin.android) alias(libs...