-
안드로이드 비동기 처리 2-5 (네트워크 통신 - retrofit)안드로이드 학습/Android 기술면접 대비 코드 2024. 11. 1. 10:48
안드로이드에서 앞서 RxJava를 학습했던 것들은 UI 처리나 기타 비동기가 사용되야 하는 곳 등등을 학습했다.
- UI 이벤트 처리 (실시간 검색, 버튼 클릭)
- 네트워크 통신
- 데이터베이스
- 그 외에 비동기 방식들
이번에는 Retrofit과 함께 네트워크 통신을 하는 방법을 학습하려고 한다.
사용한 앱 스택 :
- RxJava & Retrofit
- Hilt
- databinding
- ViewModel
적용된 아키텍처 :
- Three Layer Architecture
참고 :
(1) developer 사이트 : 링크
(2) 3Layer 예제 : https://github.com/tdcolvin/PlanetSpotters
1. build.gradle(app)
먼저 Rx와 Retrofit 그리고 Hilt 라이브러리를 추가해야 한다.
plugins { id 'com.android.application' id 'org.jetbrains.kotlin.android' id 'kotlin-kapt' id 'kotlin-android' id 'com.google.dagger.hilt.android' } buildFeatures { viewBinding = true dataBinding = true compose = true } dependencies { ... 생략 ... // RxJava & RxKotlin & RxAndroid & RxBinding implementation("io.reactivex.rxjava3:rxandroid:3.0.2") implementation("io.reactivex.rxjava3:rxjava:3.1.5") implementation("io.reactivex.rxjava3:rxkotlin:3.0.0") implementation("com.jakewharton.rxbinding4:rxbinding:4.0.0") // Retrofit implementation 'com.squareup.retrofit2:retrofit:2.11.0' implementation 'com.squareup.retrofit2:converter-gson:2.9.0' // JSON 데이터 처리를 위한 Gson 컨버터 implementation 'com.squareup.retrofit2:adapter-rxjava3:2.9.0' // RxJava 3 어댑터 추가 // Dagger Hilt implementation "com.google.dagger:hilt-android:2.51.1" kapt "com.google.dagger:hilt-compiler:2.51.1" }
2. build.gradle(Project)
plugins { id 'com.android.application' version '8.1.4' apply false id 'org.jetbrains.kotlin.android' version '1.9.24' apply false id 'com.google.gms.google-services' version '4.4.2' apply false id 'com.google.dagger.hilt.android' version '2.51.1' apply false }
3. retrofit 추가
3-1) RxRetrofitTestApi
interface RxRetrofitTestApi { @GET("posts") // 데이터를 한번만 받아오기 때문에 Single을 사용한다. fun getRxRetrofitTestData(): Single<List<RxRetrofitTestDTO>> }
RxJava의 Base Classes중 Single을 사용했다. 왜냐하면 데이터를 한번만 가져올 것이기 때문이다.
3-2) RxRetrofitTestDTO
data class RxRetrofitTestDTO(val userId:Int, val id:Int, val title:String, val body:String)
데이터 형식에 맞게 DTO 생성.
더보기[ { "userId": 1, "id": 1, "title": "sunt aut facere repellat provident occaecati excepturi optio reprehenderit", "body": "quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto" }, { "userId": 1, "id": 2, "title": "qui est esse", "body": "est rerum tempore vitae\nsequi sint nihil reprehenderit dolor beatae ea dolores neque\nfugiat blanditiis voluptate porro vel nihil molestiae ut reiciendis\nqui aperiam non debitis possimus qui neque nisi nulla" }, ... 생략 ]
3-3) NetworkModulo
@Module @InstallIn(SingletonComponent::class) class NetworkModulo { @Provides @Singleton fun provideRetrofit(): Retrofit { return Retrofit.Builder() .addConverterFactory(GsonConverterFactory.create()) .addCallAdapterFactory(RxJava3CallAdapterFactory.create()) .baseUrl(Constants.URLS.BASE_URL) .build() } @Provides @Singleton fun provideApiService(retrofit: Retrofit): RxRetrofitTestApi { return retrofit.create(RxRetrofitTestApi::class.java) } }
의존성을 없애기 위해서 Dagger Hilt를 적용했다.
Retrofit에 먼저 의존성을 주입 후 RxRetrofitTestApi에도 의존성 주입.
3-4) RxRetrofitTestRepository
@Singleton class RxRetrofitTestRepository @Inject constructor( private val rxRetrofitTestApi: RxRetrofitTestApi ){ fun fetchAllRxRetrofitTestData(): Single<List<RxRetrofitTestDTO>> { return rxRetrofitTestApi.getRxRetrofitTestData() } }
Repository에서 데이터 통신을 관리한다.
현재 예제에서는 네트워크 통신한 데이터만 가져왔지만 Local DB에서 가져온 것도 Repository 같은 곳에서 같이 관리 할 수 있다.
3-5) RxRetrofitUseCases
class RxRetrofitUseCases @Inject constructor( private val rxRetrofitTestRepository: RxRetrofitTestRepository ) { fun execute(): Single<List<RxRetrofitTestDTO>> { return rxRetrofitTestRepository.fetchAllRxRetrofitTestData() .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) } }
기존 MVVM과 다른 점이 usecase를 사용한다는 점이 다르다. ViewModel은 데이터 관리만 하고 비지니스 로직을 Usecase에서 처리하게 한다.
3-6) RxRetrofitTestViewModel
@HiltViewModel class RxRetrofitTestViewModel @Inject constructor(private val rxRetrofitUseCases: RxRetrofitUseCases) : ViewModel() { private val _rxRetrofitTestData = MutableLiveData<RxRetrofitTestState<List<RxRetrofitTestDTO>>>() val rxRetrofitTestData: LiveData<RxRetrofitTestState<List<RxRetrofitTestDTO>>> get() = _rxRetrofitTestData private var disposable: Disposable? = null fun fetchAllData() { _rxRetrofitTestData.value = RxRetrofitTestState.loading() val observer = rxRetrofitUseCases.execute() disposable = observer.subscribe( { data -> _rxRetrofitTestData.value = RxRetrofitTestState.success(data) }, { error -> _rxRetrofitTestData.value = RxRetrofitTestState.error(error.message) } ) } fun dispose(){ disposable?.dispose() } }
자바의 SRP원칙에 따라 ViewModel은 데이터만 관리하게 만든다.
여기서 특이 했던 점은 데이터를 그대로 받는 것이 아니라 RxJava에서
데이터를 success, loading, error로 나눌 수 있게 데이터를 변경시켜줘서 사용한다는 점이다.
이런 방식은 처음 사용해서 가독성이 더 좋아지는 것인지 또는 다른 장점이 있는 것인지 더 학습해봐야 겠다.
3-7) RxJavaRetrofitFragment
class RxJavaRetrofitFragment : DataBindingBaseFragment<FragmentRxJavaRetrofitBinding>(R.layout.fragment_rx_java_retrofit) { private lateinit var rxRetrofitTestViewModel: RxRetrofitTestViewModel private val rxRetrofitTestAdapter by lazy { RxRetrofitTestAdapter() } override fun initContentInOnViewCreated() { rxRetrofitTestViewModel = ViewModelProvider(this)[RxRetrofitTestViewModel::class.java] rxRetrofitTestViewModel.rxRetrofitTestData.observe(this) { rxRetrofitTestState -> when (rxRetrofitTestState.status) { Status.SUCCESS -> { showLoadedData(rxRetrofitTestState.data) } Status.LOADING -> { showLoadingView() } Status.ERROR -> { showErrorMsg(rxRetrofitTestState.message) } } } binding?.apply { rxRetrofitTestVM = rxRetrofitTestViewModel btnRxRetrofitLoad.setOnClickListener { rxRetrofitTestViewModel.fetchAllData() } } ... 생략 ... }
마지막 Fragment 부분이다.
LiveData를 Observe 패턴으로 데이터 변경을 감지하게 했다.
RxJava와 Retrofit을 사용해서 네트워크 통신을 해봤다.
하지만 해보면서 느낀 것은 새로 만드는 프로젝트에는 굳이? RxJava를 넣어야 하는가에 대한 물음이었다.
프로젝트를 코루틴으로 하고 새로 만들어진 프로젝트라면 코루틴을 사용하는 것이 더 편하지 않을까 싶다.
이번에는 코루틴에 대해서 좀더 학습해봐야 겠다.
'안드로이드 학습 > Android 기술면접 대비 코드' 카테고리의 다른 글
클린 아키텍처 준비 - 1 (0) 2025.04.24 안드로이드 비동기 처리 2-4 (실시간 검색 with EditText) (1) 2024.11.01 안드로이드 비동기 처리 2-3 (Operators : 연산자들) 코드편 (1) 2024.10.31 안드로이드 Rxjava 사용하기 (1) (0) 2024.03.06 Anr 예제 (0) 2024.01.23