본문 바로가기

프로그래밍 놀이터2060

[android] 안전하게 flow 를 collect 하기! - android 에서는 보통 UI layer 에서 flow 가 collect 된다. LifecycleOwner.addRepeatingJob, Lifecycle.repeatOnLifecycle, Flow.flowWithLifecycle 등을 이용해서 쓸데없이 res 가 낭비되지 않도록 하는 방법에 대해 알아본다. 리소스 낭비 - CoroutineScope.launch, Flow.launchIn, LifecycleCoroutineScope.launchWhenX 를 사용하는 것은 Activity 가 bg 로 들어갈 때 Job 을 수동으로 취소해주지 않는 한 안전한 방법이 아니다. 위 API 들은 app 이 bg 상태에 있을 때도 flow producer 가 buffer 에 emit 을 하도록 하고, 따라서 .. 2021. 5. 11.
[coroutine] Flow vs RxJava - 이 글은 RxJava 는 써보고, Flow 는 안 써본 개발자 입장에서 정리한 글. Core functionality - view state 와 effects 를 만들고 업데이트 하기 위해 coroutine 1.3.6 부터는 StateFlow 와 MutableStateFlow 를 제공한다. Retrofit - // Flow interface FeedService { @GET("lists/{listType}") suspend fun getTweets( // suspend 를 붙여준다. @Path(LIST_TYPE_PATH listType:String, @Query(LIST_ID_QUERY) listId:String, @Query(LIST_COUNT_QUERY) count:String, @Query(LI.. 2021. 5. 10.
[android] LiveData 를 StateFlow or SharedFlow 로 교체하기 (StateFlow 와 SharedFlow 도 이해해보기) - Kotlin Coroutine 은 최근 SharedFlow 와 StateFlow 라는 2가지 type 의 Flow 를 소개했다. - LiveData 를 Flow 형태로 바꾸기 전에 LiveData 를 Flow 형태로 바꾸어야 하는 이유를 알아보자. 1. LiveData 는 UI 에 너무 bind 되어 있다. 2. LiveData 는 Android platform 에 너무 bind 되어 있다. 위의 이유로 LiveData 는 Presentation Layer 에서는 사용하기 괜찮을 수 있지만, Domain Layer 로 내려가기에는 ugly 해진다. Domain Layer 는 platform-independent 해야 하기 때문이다. - LiveData 를 pure Flow 로 교체할 수는 없다. 1... 2021. 5. 9.
[coroutine] SharedFlow & StateFlow StateFlow - StateFlow 는 observable flow 로 collector 에게 현재값과 업데이트 되는 새로운 값을 전달하는 녀석이다. 현재 값을 value property 를 통해 읽을 수도 있다. state 를 update 하고 flow 에게 그 값을 보내기 위해서는 MutableStateFlow 에 value 값을 설정해주면 된다. flow { } builder 로 만든 녀석들은 cold flow 이지만, StateFlow 는 hot flow 이다. 따라서 collect 하는 순간 최신 값을 전달받는다. - class LatestNewsViewModel(private val newsRepository: NewsRepository) : ViewModel() { // Backing p.. 2021. 5. 8.
[RxJava] 햇갈리던 subscribeOn, observeOn 의 thread 관계 정리 - subscribeOn 은 최초 호출의 것만 valid 하고, 그 이후에 사용하는 것은 모두 무시된다. - subscribeOn 은 처음 시작부분의 thread 를 결정하고, observeOn 을 만나는 순간부터 observeOn 에서 명시한 thread 로 변경된다. - just 를 사용하면 subscribe 시점이 아니라, 호출되는 시점에 바로 연산이 수행된다. subscribeOn 에서 명시한 thread 가 아닌 just 를 호출한 thread 에서 바로 호출된다. 메인에서 호출하면 loadDataSync 자체는 mainThread 에서 연산된다는 것이다. 그림에서 빨간 줄이 약간 혼란스러움을 줄 수 있는데, subscribing 자체는 io thread 에서 잘 수행된다. 이 말은 연산 자체는.. 2021. 5. 7.
[android] Write asynchronous DAO queries - Room 에 대해 알아보자 - UI 에서 query 하는 것을 막기 위해 room 은 main thread 에서 db 에 접근하는 것을 허락하지 않고 있다. 이 말은 DAO query 를 async 로 해야 한다는 것을 의미한다. Room lib 은 async query 를 위해 여러개의 framework 를 통합시켰다. - DAO query 는 3개의 category 로 구분될 수 있다. insert, update, delete 등의 one-shot write query one-shot read query observable read query Language and framework options - One-shot write Coroutines(suspend) Single, Maybe, Completable Listenabl.. 2021. 5. 6.
[android] Referencing complex data using Room - Room 에 대해 알아보자 - Room 은 primitive 와 boxed type 에 대한 converting 기능을 제공한다. 그렇지만 object reference 에 대한 converting 은 제공하지 않는다. Use type converters - Single db column 에 custom data type 을 mapping 하고 싶을 때가 있을 것이다. 이 기능을 지원하기 위해서는 TypeConverter 를 제공해야 하는데, 이 녀석은 custom class 를 Room 이 아는 type 으로 변환하는 기능을 제공한다. 예를 들어 Date 를 TypeConverter 를 통해 Unix timestamp 형태로 변환할 수 있다. class Converters{ @TypeConverter fun fromTimesta.. 2021. 5. 5.
[android] Testing your database - Room 에 대해 알아보자 - 2가지 테스트 방법이 있다. 하나는 android 단말에서 테스트. 다른 하나는 host 개발 장비에서 (not recommended) - 테스트를 앱에서 돌릴 때 Room 은 DAO class 에 대한 mock 생성을 허용한다. 그래서 full db 를 만들 필요 없이 테스트 할 수 있다. 이 기능은 DAO 가 db 에 대한 detail 을 제공하지 않기에 가능하다. Test on an Android device - db 테스트로 권유되는 방법은 Android 단말 위에서 도는 JUnit test 를 돌리는 것이다. 이 테스트는 acivity 를 만들 필요도 없고, UI test 보다 훨씬 빠르기 떄문이다. - test 를 세팅하면, in-memory version 의 db 를 만들어 테스트 하면 .. 2021. 5. 4.
[android] Migrating Room databases - Room 에 대해 알아보자 - Room 은 Migration class 를 써서 db 변화가 있을 때 migrate 를 할 수 있게 해준다. Migration class 는 startVersion 과 endVersion 을 명시한다. runtime 에 Room 은 각각의 Migration class 의 migrate() 함수를 호출해준다. val MIGRATION_1_2 = object : Migration(1, 2){ override fun migrate(db: SupportSQLiteDatabase){ db.execSQL("CREATE TABLE 'Fruit' ('id' INTEGER, 'name' TEXT, PRIMARY KEY('id'))") } } val MIGRATION_2_3 = object : Migration(2,.. 2021. 5. 3.
반응형