대이동: Rxjava에서 협동 프로그램으로
28976 단어 androidcomputersciencecareerkotlin
A detailed guide to refactoring code from rxJava to coroutines.
This post assumes you are familiar with rxJava, MVVM architecture and have a basic knowledge of coroutines.
rxJava를 광범위하게 사용하는 프로젝트가 있다고 가정하십시오.왜 안 하냐고!이것은 비동기성과 이벤트 기반의 논리를 처리하는 좋은 방법이다.많은 조작자들이 선택할 수 있고, 라인이 더욱 간단하고 추상적으로 변하며, 응용 프로그램의 각 층에서 오류를 처리하는 데 많은 노력이 필요하지 않다.덥고 차가운 관찰, 지연, 간격, 넘침 전략 등이 있는데, 그것들은 우리가 복잡한 용례를 해결하는 데 도움을 준다.만약 2년 전에 rxJava를 도입하지 않았다면, 나는 안드로이드에서 기업급 응용 프로그램을 개발하기 시작하지 않았을 것이다!
내가 여기 있는 목표는 네가 합작으로 전향하도록 설득하는 것이 아니다.프로젝트에서 사용하기를 기대하고 rxJava로 작성된 코드 라이브러리와 관련된 부분을 협동 프로그램으로 재구성하는 것을 고려했다고 가정합니다. 이것은kotlin1.3에서 안정적으로 도입된 것입니다.
협동 루트는 일종의 병행 설계 모델로 비동기적이고 비저항 코드를 작성하는 것을 더욱 쉽게 한다.
이 프로젝트는 다음과 같은 체계 구조를 사용한다
Dell의 비즈니스 논리는 다음과 같습니다.
viewModel의 한 부분을 살펴보겠습니다. rxJava와liveData를 사용하고usecase 클래스를 요청한 후에 데이터를 관찰한 다음 적절한 상태 알림 UI로 나타냅니다.
override fun getListOfCountries() {
compositeDisposable.add(
countryListUseCase.subscribeForData()
.doOnSubscribe {
countryListViewStates.postValue(ViewStates.CountryListStates.ShowLoading)
}
.subscribeOn(schedulerProvider.io())
.subscribe({ countryListDataWrapper ->
when (countryListDataWrapper) {
is UseCaseWrapper.Success -> {
// create a state when data is available to display
val currentState = ViewStates.CountryListStates.ShowContent(
isLoading = false,
hasError = false,
errorMessage = "",
showList = true,
countryList = countryListDataWrapper.data.list
)
//post the current state to liveData
countryListViewStates.postValue(currentState)
}
is UseCaseWrapper.Failed -> {
//create an error state when no data is available to display
val currentState = ViewStates.CountryListStates.ShowContent(
isLoading = false,
hasError = true,
errorMessage = NO_NETWORK,
showList = false,
countryList = ArrayList()
)
//post the current state to liveData
countryListViewStates.postValue(currentState)
}
}
}, {
//create a state for handling generic errors
val currentState = ViewStates.CountryListStates.ShowContent(
isLoading = false,
hasError = true,
errorMessage = SOMETHING_WENT_WRONG,
showList = false,
countryList = ArrayList()
)
//post the current state to liveData
countryListViewStates.postValue(currentState)
})
)
}
이제 시너지 라우팅을 사용하는 동일한 논리의 코드 세그먼트를 살펴보겠습니다. override fun getListOfCountries() {
viewModelScope.launch {
when (val useCaseData = countryListUseCase.requestForData()) {
is UseCaseWrapper.Success -> {
//retrieve data received for success
val listOfCountries = useCaseData.data.list
val currentViewState = CountryListStates.ShowContent(
isLoading = false,
hasError = false,
errorMessage = "",
showList = true,
countryList = listOfCountries
)
//setting this view state as the current state of the stateFlow
countryListViewStates.value = currentViewState
}
is UseCaseWrapper.Failed -> {
//creating a state for failed events
val currentViewState = CountryListStates.ShowContent(
isLoading = false,
hasError = true,
errorMessage = useCaseData.reason.value,
showList = false,
countryList = ArrayList()
)
//setting this view state as the current state of the stateFlow
countryListViewStates.value = currentViewState
}
}
}
}
우리는viewModel에서 데이터를 관찰하는 부분에 변화가 거의 없다.usecase 클래스의 rxJava의 onError 블록을 처리했습니다.
다음은 usecase 클래스 rxJava 버전의 Getter 방법입니다. 우리는 논리를 작성하여 데이터를 얻고publishSubject를 통해 데이터를 보냅니다.
override fun subscribeForData(): Observable<UseCaseWrapper<DataWrapper>> {
compositeDisposable.add(
countryApiRepo.getData()
// don't block the main thread
.subscribeOn(schedulerProvider.computation())
// store API response to local storage
.flatMap { return@flatMap syncDataToLocal(it) }
// convert network layer models to domain models for UI consumption
.compose(transformCountryObjects())
// put data inside a wrapper for viewModel usage
.map { return@map mapToDataWrapper(Source.NETWORK, it) }
// get data from local storage in case api call throws error
.onErrorResumeNext(getDataFromLocal())
.subscribe({ wrappedData ->
// There is no internet and cached data is unavailable
if (wrappedData.source == Source.LOCAL && wrappedData.list.isEmpty()) {
dataRepo.onNext(UseCaseWrapper.Failed(ReasonToFail.NO_NETWORK_AVAILABLE))
} else {
// Data is available, either from cached or from network
dataRepo.onNext(UseCaseWrapper.Success(wrappedData))
}
}, {
// Handle generic exceptions
dataRepo.onNext(UseCaseWrapper.Failed(ReasonToFail.SOMETHING_WENT_WRONG))
})
)
return dataRepo
}
용례류는 응용 프로그램의 업무 논리를 봉인했다.위의 rxJava 구현에서subscribeForData () 함수를 수동 함수로 만듭니다.만약 당신이 문법을 한 번 본다면, 솔직히 말하면, rxJava에 익숙하면, 그것은 매우 간결하고 이해하기 쉽다.하지만 당신이 1분 동안 생각해 보면, 우리는 정말 반응적으로 용례를 해결해야 합니까?캐시된 API 응답을 네트워크가 없을 때 되돌려줍니다. 이것은 우리가 시도하고 있는 것입니다.만약 네가 나에게 물었다면, 나의 졸견으로 볼 때, 우리가 코드를 수동적으로 만든 것은 단지 rxJava를 사용했기 때문이다.따라서 우리가 사용하는 도구는 우리의 범례를 정의하는 것이다.
시너지 버전을 살펴보겠습니다.
override suspend fun requestForData(): UseCaseWrapper<DataWrapper> {
return try {
//get data from either network of Local
val (dataResponse, dataSource) = getDataFromAvailableSource()
if (dataSource == Source.NETWORK) {
//sync to file storage if response is from network
syncDataToLocal(dataResponse)
}
//convert network layer model to domain layer model for UI consumption
val mappedApiResponse = mapRawDataToModelClass(dataResponse)
val dataWrapper = DataWrapper(mappedApiResponse, dataSource)
//return data successfully on completion
UseCaseWrapper.Success(dataWrapper)
} catch (thrownExceptions: UseCaseException) {
/*
handle exception caused by any of the local
functions and relay the same to UI layer
*/
UseCaseWrapper.Failed(thrownExceptions.reason)
} catch (genericExceptions: Exception) {
// generic exception handling
UseCaseWrapper.Failed(ReasonToFail.SOMETHING_WENT_WRONG)
}
}
coroutines 용례 클래스를 보십시오. 위에서 공유한 rxjava 클래스에 비해 현저한 변화를 볼 수 있습니다.협동 프로그램 구현 중, 우리는 모든 단독 논리 코드 블록에 단독 마운트 함수를 만들었다.이 함수들 중 하나는 withContext () 블록에서 협동 프로그램 역할 영역을 사용해서 실행됩니다. 이것은 우리가 메인 라인 밖에서 직렬 방식으로 이 작업을 실행하는 데 도움이 됩니다.이것은 라인을 간소화하고 반응성을 강제로 집행하지 않는다.예를 들어, 다음 함수는 API 응답을 파일 저장소에 기록하고 다른 함수도 포함합니다.
private suspend fun syncDataToLocal(networkResponse: CountryListResponse) {
withContext(Dispatchers.Default) {
val content = gson.toJson(networkResponse)
fileRepository.saveDataToLocal(content)
}
}
이제 사용자 인터페이스의 변경 사항을 어떻게 알려주는지 다른 중요한 부분을 살펴보자.rxJava 코드에서, 우리는 liveData를 사용하여viewModel과view 사이를 통신하고, 보기에서 liveData를 관찰합니다. (이 예는 세션입니다.) private fun observeViewSates() {
sharedViewModel.observeViewStates().observe(viewLifecycleOwner, Observer { viewStates ->
when (viewStates) {
is ViewStates.CountryListStates.ShowLoading -> {
//show loader
}
is ViewStates.CountryListStates.ShowContent -> {
//render content state
}
}
})
}
다음은 협동 프로그램을 사용하는 대응 항목이다. private fun observeViewSates() {
uiStateJob = lifecycleScope.launchWhenStarted {
sharedViewModel.observeViewStates().collect { viewStates ->
when (viewStates) {
is CountryListStates.ShowLoading -> {
//show loader
}
is CountryListStates.ShowContent -> {
//render content state
}
}
}
}
}
여기서, 우리는viewModel에서 StateFlow (뜨거운 관찰 대상) 를 사용하여 UI의 상태를 유지하고, 보기에서 그것을 수집하고 있습니다.다음은viewModel에서 stateFlow를 초기화하는 방법입니다.
private val countryListViewStates = MutableStateFlow<CountryListStates>(
CountryListStates.ShowLoading
)
다음은stateflow와liveData 사이의 차이점--stateflow가liveData보다 약간의 장점이 있다
그러나 이것은 추가 대가를 치러야 한다.
따라서 라이프 사이클 감지의 라이브 데이터를 원하느냐, UI 층의 State Flow를 원하느냐는 논리를 어떻게 처리하느냐에 달려 있다.
rxJava는 좋은 학습 곡선을 가지고 있다.일단 네가 익숙해지면, 그것은 의심할 여지없이 생명을 구하는 볏짚이다.그러나 우리가 이렇게 절박하게 반응할 필요가 없는 부분에서 우리는 협동 프로그램으로 쉽게 전환하고 효과적으로 일을 완성할 수 있다.
다음은github에 있는 항목의 링크입니다.주 분기에는 rxJava 코드가 있고 분기 분기 coroutine에는 coroutine 마이그레이션 코드가 있습니다.
무크제예비치 / 국가 명단
국가 명단
오픈 API에서 국가 목록을 가져와 회수기 보기에 표시하는 안드로이드 응용 프로그램
응용 프로그램은 MVVM 구조를 사용하는데, 아래는 structire이다
개방형 API에서 국가 목록을 가져와 파일 시스템에 캐시했습니다.
네트워크가 없을 때, 우리는 캐시된 데이터를 되돌려줍니다
캐시에 사용할 수 있는 데이터가 없으면 사용자에게 오류를 표시합니다.
이 앱은 RXJava를 사용해 다거 안드로이드와 함께 기술 스택으로 개조했다.
View on GitHub
표지 사진 작성자Mariko margetson가 Unsplash
Reference
이 문제에 관하여(대이동: Rxjava에서 협동 프로그램으로), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://dev.to/mukherjeeavik/the-great-migration-from-rxjava-to-coroutines-4n22
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
Reference
이 문제에 관하여(대이동: Rxjava에서 협동 프로그램으로), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/mukherjeeavik/the-great-migration-from-rxjava-to-coroutines-4n22텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)