๐ฒ ์ค๋์ ๊ฐ๋ฐ ์ผ์ง
- Clean Architecture์์ Paging์ ์ ์ฉ์ํค๋๋ฐ ์ ๋ฅผ ๋จน์๋ค.
- ์๋ ViewModel์์ PagingSource๋ฅผ ์์๋ฐ๋ ํด๋์ค๋ก Page ๊ฐ์ ๊ฐ์ ธ์ค๋๋ฐ Clean Architecture ๊ตฌ์กฐ๋ก ํด์ผํ๊ธฐ์ ViewModel์๋ UseCase๋ง ๋ฃ์๋ค.
- Api๋ก๋ถํฐ Page๊ฐ์ ๋ฐ์์ค๊ณ -> DataSource์์ Repository๋ก ๊ฐ์ ๊ทธ๋๋ก ๋๊ฒจ์ค๋ค -> Repository์์ Paging ์ฒ๋ฆฌ๋ฅผ ํด์ค ํ PagingSource.LoadResult ๊ฐ์ ๋ฐํํ๋ค.
- Repository๋ Domain ์์ญ์ด๊ธฐ์ ์๋๋ก์ด๋์ ์์กดํ๋ฉด ์๋ผ์ Paging์ ์๋์ ๊ฐ์ด implent ํ๋ค.
1 2
// Paging3 implementation "androidx.paging:paging-common:3.1.1"
์๋ฒ์ ํต์ ํ๋ ๊ณผ์ ์์ ์นด์นด์ค์ ๋ค์ด๋ฒ์์ ๋ฐ์ ํ ํฐ ๊ฐ์ ๋๊ฒจ accessToken ๊ฐ์ ๋ฐ์์์ผํ๋๋ฐ ์๊พธ 500 error๊ฐ ๋ฐ์ํ๋ค.
- ์๊ณ ๋ณด๋ ์๋ฒํํ ๋๊ธฐ๋ ํ ํฐ๊ฐ ๋ง์ง๋ง์ด โ=โ์ผ๋ก ๋๋๋๋ฐ ์ด๊ฒ ์ธ์์ด ์๋ผ์ ์ ๋์ฝ๋๋ก ๋ณ๊ฒฝ๋์ด ์๋ฒ์ ์ ์ก๋๋ค.
- ๊ฒ์ํด๋ณธ ๊ฒฐ๊ณผ gson ์ค์ ์ ๋ฐ๊ฟ์ฃผ๋ฉด ๋์๋ค.
1 2 3 4 5 6 7
val gson = GsonBuilder().disableHtmlEscaping().create() Retrofit.Builder() .baseUrl(SERVER_URL) .client(OkHttpClient.Builder().addInterceptor(interceptor).build()) .addConverterFactory(GsonConverterFactory.create(gson)) .build()
์๋ฒ์ ํต์ ํ ๋ ๊ฒฐ๊ณผ๊ฐ ํด๋์ค๋ฅผ ํ๋ ๋ง๋ค์ด์ ํต์ ํ๋ ๋ง์ด ํธํ๋ค.
- ์ด์ฒ๋ผ ResultState๋ผ๋ ํด๋์ค๋ก ํต์ ๊ณผ์ ์ ๋ํ๋ผ ์ ์๋ค.
1 2 3 4 5 6 7 8 9
sealed class ResultState<out T> { object Uninitialized : ResultState<Nothing>() object Loading : ResultState<Nothing>() object Empty : ResultState<Nothing>() data class Success<T>(val data: T) : ResultState<T>() data class Error(val exception: Throwable) : ResultState<Nothing>() { val isNetworkError = exception is IOException } }
ํต์ ๊ณผ์
1 2 3 4 5 6 7 8
override fun loginNaverUser(token: String): Flow<ResultState<User>> = flow { Log.d(TAG, "loginNaverUser: $TAG: Loading") emit(ResultState.Loading) userRemoteDataSource.loginNaverUser(token).collect { Log.d(TAG, "loginNaverUser $TAG: collect ${it.body()!!}") emit(ResultState.Success(mapperToUser(it.body()!!))) }
์ด๋ ๊ฒ ์ฒ์์ Loading ์ํ๋ก ์ค์ ํ๊ณ ๊ฐ์ ๋๊ธฐ๋ฉด์ Success ์ํ๋ก ๋ฐ๊ฟ์ค๋ค.
- ์ด ๊ฒฝ์ฐ๋ flow๋ ๊ฐ์ด ์ฌ์ฉํ๋ฉด ๋ง์ด ํธํ ๊ฒ ๊ฐ๋ค.
- flow๋ถํฐ ๊ณต๋ถํด์ผํ ๋ฏโฆ.