ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Coroutine + Retrofit | Coroutine + Room
    개발/안드로이드 2021. 7. 22. 21:00

    Coroutine + Retrofit

     

    Retrofit 2.6.0 버전부터 suspend 함수로 api를 작성할 수 있게 됐다. 다른 Retrofit 인터페이스처럼 어노테이션을 추가하고 suspend 함수를 추가하면 빌드 될 때 Retrofit 에서 전처리한다. 

     

    interface LibraryApi {
        @GET("/1.0/new")
        suspend fun getNew() : BookListResp
    }

     

    suspend로 쓰였기 때문에, api 를 호출하는 부분에서도 suspend 함수를 받아서 처리할 수 있다. 예로 Repository 인 경우 suspend 함수를 이용해서 아래 코드로 표현이 가능하다. withContext를 받아서 I/O 쓰레드에서 실행하도록 변경해 Main 쓰레드 안전성이 보장됐다.

     

    class LibraryRepository(
        private val apiProvider: ApiProvider
    ) {
    
        private val libraryApi by lazy { apiProvider.createApi(LibraryApi::class.java) }
    
        suspend fun loadNew(): BookListResp = withContext(Dispatchers.IO) {
            return@withContext libraryApi.getNew()
        }

     

    Coroutine + Room 

     

    Room에서 데이터 변화에 따라 UI를 바꾸거나 특정 로직을 실행해야할 때가 있다. Room 에서는 LiveData와 Flow를 이용하는 두가지 방법을 제공하는데, 이 포스트에서는 Flow를 활용한 버전만 다룬다. 

     

    @Dao
    interface BookSearchDao {
        @Query("select * from BookSearch order by BookSearch.createdAt desc")
        fun selectBookSearchList(): Flow<List<BookSearch>?>
        
    class LibraryRepository(
        private val bookSearchDao: BookSearchDao
    ) {
        suspend fun loadBookSearchHistory(): Flow<List<BookSearch>?> = withContext(Dispatchers.IO) {
            return@withContext bookSearchDao.selectBookSearchList()
        }

     

    Dao의 리턴타입을 Flow로 싸고 Repository 에서는 suspend 함수를 이용해 IO 쓰레드에서 실행하도록 변경하고 리턴했다. Flow는 RxJava의 Flowable과 같아서 내부 DB에 변경사항이 생기면 스트림을 따라서 알림을 준다. 

     

    class SearchViewModel @Inject constructor(
        private val libraryRepository: LibraryRepository
    ): ViewModel() {
        fun loadHistory() {
            viewModelScope.launch {
                libraryRepository.loadBookSearchHistory()
                    .distinctUntilChanged()
                    .collect { list ->
                        searchHistory.value = list ?: listOf()
                    }
            }
        }

     

    ViewModel에선 loadBookSearchHistory() 함수의 리턴값인 Flow를 viewModelScope 내에서 subscribe 한다. 변화가 있을 때마다 collect 내부의 바디 코드가 실행된다. viewModelScop 으로 실행했기 때문에 ViewModel이 종료되면 subscribe도 자동으로 종료된다.

    '개발 > 안드로이드' 카테고리의 다른 글

    RxJava dispose()  (0) 2021.09.16
    ListAdapter, DiffUtil  (0) 2021.08.20
    suspend fun  (0) 2021.07.22
    Single, Maybe, Completable  (0) 2021.07.04
    Serializable 과 Parcelable  (0) 2021.06.19

    댓글

Designed by Tistory.