안드로이드 88

Google I/O Extended Seoul 2023: Dagger Hilt로 의존성 주입하기

https://speakerdeck.com/fornewid/dagger-hiltro-yijonseong-juibhagi @네이버 웹툰 안성용님 발표자료를 글로 옮긴 것입니다. 의존성 주입이란? 의존성 주입은 하나의 객체가 다른 객체의 의존성을 제공하는 기법. 의존성 주입의 의도는 객체의 생성과 사용의 관심을 분리하는 것. // 의존성 주입 X class Car { private val engine: Engine = Engine() fun start() { engine.start() } } // 의존성 주입 예시 - 생성자에서 전달 class Car(private val engine: Engine) { fun start() { engine.start() } } // 의존성 주입 예시 - 필드 주입 clas..

[안드로이드] 회전목마(Carousel) 애니메이션 구현하기

게임에서 아이템이나 캐릭터 선택을 할때 회전 목마처럼 돌아가는 선택 애니메이션을 자주 볼 수 있는데, 이것을 안드로이드에서 구현해 볼 수 있는 기회가 생겼다. 사실 노가다를 하면 어떻게든 구현할 수 있지만, 이번에는 문제를 분석하고 쪼개보는 연습을 겸해봤다. 💡 요구사항: 3가지 종류의 상자가 있고, 이 상자들을 돌려가면서 열 상자를 선택하게 해주세요. 1. 상자 유형 데이터화 첫번째로 해야할 일은 상자를 데이터화하는거다. enum 클래스로 상자의 이미지, 가격, 이름이 담긴 LuckyBoxType을 만들어 주었다. enum을 사용한 이유는 순차적 접근이 sealed class보다 훨씬 쉽기 때문이다. enum class LuckyBoxType( val image: Int = 0, val cost: In..

[안드로이드] ExoPlayer 깜빡거리거나 검은 화면(Black screen)이 뜰 때

문제발생 Epoxy로 무한 반복되는 배너 캐러셀에 동영상을 적용시키는 중에, 간혹 동영상이 재생될때 검은 화면만뜨고 재생이 안되거나 깜빡이는 문제가 있었다. *하나의 ExoPlayer를 RecyclerView.Adapter에서 재활용해가면서 쓰는 사례다. 정신차리고 setPlayer() Document를 자세히 읽어보니... Player를 다른 View에 붙일때 switchTargetView()를 쓰는걸 추천한다고 되어있다. 하지만 setPlayer()를 직접 쓰고자 할 경우 이전 View에서 Player를 분리하기 위해 setPlayer(null)을 호출하기 이전에 새로운 View에 Player를 연결시켜야 한다. *switchTargetView를 직접 써보려고 했으나, 지원하지 않는 메소드였다. 해결..

[안드로이드] java.lang.IllegalStateException: An instance of OnFlingListener already set 해결

문제 발생 @ModelView(autoLayout = ModelView.Size.MATCH_WIDTH_WRAP_HEIGHT) internal class PagerSnapHelperCarousel @JvmOverloads constructor( context: Context ) : Carousel(context) { init { if (onFlingListener == null) { PagerSnapHelper().attachToRecyclerView(this) } } } Epoxy의 Custom Carousel로 SnapHelper를 붙이는 도중 OnFlingListener가 이미 등록되어있다는 오류가 발생했다. 당연하게도 이유는 RecyclerVIew에 OnFlingListener가 이미 등록되어 있어..

[CI/CD] Firebase Test Labs UI Test 자동화하기

CI/CD Tool로 Bitrise (CLI)를 사용하고 있는데, Workflow에 UI Test 단계를 추가해보려고한다. gn_test Workflow를 살펴보면, git pull 로 프로젝트를 땡겨오고, 이전에 만든 test용 apk를 제거한다. UI Test용 빌드를 생성하고, Firebase Test Lab으로 기기에 테스트 한다. gn_test: steps: - script@1: inputs: - content: "bash $ROOT/scripts/gitpull.sh" - script@1: inputs: - content: "bash $ROOT/scripts/delete_test_apk.sh" - android-build-for-ui-testing@0: inputs: - project_locat..

[안드로이드] 예제로 보는 NavigationComponent

Navigation Component란? 기존의 안드로이드에서는 여러 단계의 Fragment 진행을 추적하고, 다루기 어려웠다. Jetpack의 Naviagtion Component는 이러한 문제를 개선하기 위해서 등장했는데, iOS의 스토리보드처럼 여러 화면 이동을 그래프(Graph)로 시각화하여 보여주고 NavController를 이용해 한 곳에서 전환을 관리할 수 있도록 도와준다. “오~좋은건 알겠는데, 다음 프로젝트에 써야지^^”라는 생각이 스친다! 당장 레거시 코드에서 어떻게 활용하면 좋을지 막막할 것이다. (내가 그랬기때문) 그래서 회원가입을 예로 들어서, 현재 진행중인 프로젝트에 Navigation Component를 사용하는 방법을 포스팅해보겠다. # 간단한 개념 3가지 NavGraph: ..

[안드로이드] HiltWorker 오류 Could not create Worker 해결방법

HiltWorker로 Worker에 의존성 주입받기 우선 필요한 dependency는 다음과 같다. Coroutine은 예시에서 CoroutineWorker를 만들 것이기때문에 넣어주었다. implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.1" implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.5.1' implementation "com.google.dagger:hilt-android:2.38.1" kapt "com.google.dagger:hilt-android-compiler:2.38.1" implementation("androidx.hilt:hilt-work:1...

[안드로이드] View를 터치 입력에 따라 회전하기 (핸들 구현)

이번에 만들어볼 것은 사용자의 터치 입력에따라 회전하는 핸들뷰다. 다양하게 활용할 수 있는데, 회사에서 뽑기 기계를 만들어보자는 아이디어에서 삼각함수로 뽀리면 되겠는데?! 라는 생각에서 만들어서 검증해보았다. xml은 터치 입력을 받을 view_touch와 ImageView인 handle 단 두개로 이루어져있다. center에는 touch view의 가운데 지점을 저장하고, handle 이미지 뷰를 정 중앙으로 옮긴다. val viewTouch = findViewById(R.id.view_touch) val handle = findViewById(R.id.handle) val center = PointF() viewTouch.viewTreeObserver.addOnGlobalLayoutListener(o..

[Android] 멋진 오픈소스 프로젝트 모음 - Awesome Android Kotlin Apps

https://github.com/androiddevnotes/awesome-android-kotlin-apps GitHub - androiddevnotes/awesome-android-kotlin-apps: 👓 A curated list of awesome android kotlin apps by open-source contribu 👓 A curated list of awesome android kotlin apps by open-source contributors. - GitHub - androiddevnotes/awesome-android-kotlin-apps: 👓 A curated list of awesome android kotlin apps by open-source c... github.c..

[Android] IllegalStateException: Method addObserver must be called on the main thread

문제발생 IllegalStateException: Method addObserver must be called on the main thread ViewModel을 가지고 뭔가 하려했을때 해당 오류가 발생하는 경우가 있다. 이것은 ViewModel을 lazy init해서 사용할 시에 발생하게 되는데, 나의 경우에는 아래와 같은 코드에서 발생했다. private val splashViewModel by viewModels() override fun onStart() { super.onStart() lifecycleScope.launch(Dispatchers.IO) { splashViewModel.doSomething() } } 원인 처음에는 "무슨 소리야 옵저버같은거 안붙였는데"라고 반발이 올라왔지만, 컴..