전체 글

Never stop acting like the new one on the team
Android/Development Tips

알고 계시나요 Fragment 가 복원되는 시점?

A Activity 에 B Fragment 가 있는 상황에서 A Activity 의 복원이 일어나면, A Activity 의 onCreate 보다 B Fragment 의 onViewCreated 가 먼저 호출됩니다. (정확하게는 A Activity super.onCreate 호출 -> B Fragment 의 onViewCreated 호출 -> A Activity onCreate 호출로 진행됩니다) 따라서 A Activity onCreate 에서 어떤 값을 초기화해주고, B 의 onViewCreated 에서 무언가에 접근하는 코드가 있다면 크래시가 발생하게 됩니다. 복원이 아닌 일반적인 경우는 A activity onCreate 이후 B Fragment onViewCreated 가 호출됩니다. 문제가 생겼..

Android/Development Tips

BroadcastReceiver 사용할 때 유의점

BroadcastReceiver 를 상속 받아 사용할 때, 마치 싱글턴으로 관리 될 것 처럼 생겼지만, hashCode 찍어보면 매번 생성되는 것을 알 수 있다. 따라서 AppWidgetProvider 를 상속 받아 사용할 때 멤버 변수에 값을 저장하고 사용하는 방식등은 초기화 되기 때문에 조심해야한다. 위젯 좋은 예제

Android/Today I Learned

Android Font 고군분투기

몇일전 기능 구현후 테스트 하는 과정에서 Font 관련 함수에서 특정한 상황에 크래시가 나는 상황을 경험했습니다. 멋진 팀원들의 도움을 받아 어떤식으로 해결하였는지 공유합니다. 크게 1. 왜 크래시가 났는지? 2. 왜 간헐적으로 났는지? 3. 크래시가 나지 않았을 때는 어떤 클래스에서 이를 해소해주고 있었는지? 에 대한 내용으로 구성됩니다. 문제가 생긴 함수는 아래와 비슷한 식의 Font 의 id 를 가져와서 적용해주는 코드였습니다. // 예시 함수 fun TextView.setFont(@FontRes fontRes: Int) = apply { typeface = ResourcesCompat.getFont(context, fontRes) } 크래시 재현 상황은 앱 시작하자마자 특정 화면으로 이동하거나, ..

Android/Development Tips

Coil 썸네일 구현하기

Coil 은 썸네일 기능을 따로 제공하지 않고 있습니다. 이때 사용해 볼 수 있는 확장 함수 입니다. fun ImageView.loadOriginalImage(originUrl: String, thumbnailUrl: String) { CoroutineScope(Dispatchers.Main.immediate).launch { val thumbnail = async(Dispatchers.IO) { val request = ImageRequest.Builder(context) .data(thumbnailUrl) .build() Coil.execute(request).drawable } val original = async(Dispatchers.IO) { val request = ImageRequest.Bu..

Android/Today I Learned

Coil 로 OnDemand-image-resizing 적용하기

중요) 본 글은 원하는 사이즈를 보냈을 때 리사이즈 해주는 서버가 필요합니다. 이전에 회사에서 Glide -> Coil 로 마이그레이션 작업을 진행하면서 경험한 내용으로 이미지 사이즈에만 중점을 두고 있습니다. 또한 기승전결이 부족하고 도움이 되지 않을 수도 있습니다. OnDemand image resizing 이란 ? - 클라이언트의 요청에 따라 리사이징 된 이미지가 제공 되는 것을 의미합니다. 일단은 Coil 라이브러리내에서 사이즈 관련하여, 이미지를 효율적으로 로드하기 위한 방법이 존재하기 때문에 이부분을 먼저 보고 가겠습니다. sizeResolver 부분이 이미지를 로드할 때, 사이즈를 결정하는 부분입니다. 따로 명시적으로 처리하지 않으면, resolveSizeResolver() 함수가 불리우게 ..

Android/Today I Learned

Glide cache 제거 하기

몇일 전 회사에서 컴포즈와 코루틴의 성능을 최대화 시키기 위해 Glide 에서 Coil 로 Migration 하는 작업을 진행하였습니다. Glide 디펜던시를 모두 제거하고 이후에, Glide 에서 사용하는 Cache Directory 도 정리해주는 작업을 진행하였습니다. 따로 Cache Directory path 를 명시적으로 잡아서 사용하지 않고 있다면 아래 코드에서 Cache Directory path 를 찾을 수 있습니다. 따라서 아래와 같은 느낌으로 코드를 작성해주면 됩니다. // 경우에 따라서 workerThread, mainThread 골라서 사용하면 될 것 같습니다 val defaultGlideCacheName = "image_manager_disk_cache" context.cacheDi..

Android/Development Tips

안드로이드 하드웨어 비트맵

이전 글 : https://nanamare.tistory.com/170 와 관련이 있습니다. 몇일 전 아래와 같은 에러를 다시 만났습니다. Software rendering doesn't support hardware bitmaps 해당 이슈는 아래와 같은 코드에서 발생했습니다. canvas.drawBitmap(bitmap, width, height, paint); 결론적으로 "위 코드의 bitmap 이 하드웨어 비트맵이기 때문에, CPU 에 정보가 있지 않아 그려낼 수 없다." 가 원인이였는데, 이전글에서 bitmap 을 가져올 때, ALLOCATOR_SOFTWARE 옵션을 주기 때문에 아마 다른 원인이 있을 것이라고 생각하고 코드를 확인해봤습니다. uri 에서 bitmap 을 변환 시키는 것이 아닌 ..

Android/Development Tips

ViewModel 에서 Fragment, Activity 로 콜백을 조심하자

ViewModel 의 라이프 사이클은 Activity 나 Fragment 보다 길기 때문에 ViewModel 에서 Fragment, Activity 에 콜백 받는 것은 실수를 유발합니다 (ViewModel 에서든) 라이브데이터나 플로우를 사용하여 관찰(observe) 혹은 수집(collect) 하는 것이 좋습니다. // Activity or Fragment.kt viewModel.loadItemList() { list -> // Activity 가 Destroy 상태거나 Fragment 인 경우 not Attached 일 수 있음 // 또한 isDestroyed 혹은 isAdd 와 같은 상태를 확인하는 처리가 필요하게 됩니다 adapter.submitData(list) }

Android/Today I Learned

멀티 모듈에서 Missing required view with ID 에러 해결

몇일전 일을 하는 도중 아래와 같은 이슈를 만났습니다. Fatal Exception: java.lang.NullPointerException Missing required view with ID: com.{package}.debug:id/{resource_id} ViewBinding 을 사용하고 있는데, xxxxBinding 클래스에서 해당 아이디를 찾지못하는 이슈였습니다. 해당 레이아웃 파일에 들어가서 확인해보니, 아이디가 잘 선언되어 있고, ctrl + 클릭 조합으로도 리소스가 잘 이어져있는 것을 확인했습니다. 잠시 등에 땀이 흐를뻔했지만, 혹시나해서 같은 바인딩 클래스가 있는지 확인해봤습니다 . A 모듈에서 xxxxBinding 클래스가 사용되고 있었고, B 모듈에서도 xxxxBinding 클래스가..

Nanamare
TEAM > SELF