View
Rxjava 적용....
이번에 글은 Rxjava 적용을 하던 중 문제가 생겨서 4일동안 고민하고 별의 별 방법을 해보던 중 겨우 겨우 해결되어 글을 포스팅하게 되었다.(아..등잔 밑이 어두웠다. 솔직히.....)
자 그럼 무엇 때문에 내가 이렇게 고민을 하게 되었는지 알아보자
과연 무엇이 나를 이렇게 만들었는가?...(내 4일....)
일단 무엇인지 알기전에 글쓴이의 보험을 하나 깔고 갈까 한다. 나는 Rxjava를 많이 사용해보지 않았다. 누가 봤을 때 이게 무슨 Rxjava냐!!! 라고 하면 할 말이 없다. "나 Rxjava 응애~~ ㅠㅅㅠ" 그러니 Rxjava 괴물이라면 너그럽게 봐주길 바란다.
자 이제 진짜 알아보자
일단 나는 Rxjava를 통해서 api에서 호출한 데이터를 filter(필터링)해서 가져오고 싶었다. 간단히 말해서 ArrayList<A>의 A A객체 안에 ArrayList<B>가 있고 B객체 안에 ArrayList<A>가 있는데 이 c는 String 이다.
여기서 나는 특정 C 값에 따라서 B객체를 제거하고 싶었다. 이렇게 말하면 무슨 뜻인지 모를거 같아서 미흡한 그림판실력을 빌러서 그림으로 표현했다.
이제 조금 이해가 되길 바란다.
그리고 명칭을 조금 바꾸어 주겠다.
A -> ContentsCalendarResult
B -> RewardItemResult
c -> Time
ArrayList<C> -> StartTimes
[ContentsCalendarResult] 구조
[RewardItemResult] 구조
자 다시 말하자면 나는 RewardItemResult객체안의 ArrayList<Time>에서 특정 Time값에 따라서 RewardItemResult를 제거하거나 생존 시키고 싶은 것이다.
물론 for문을 이용해서 구현한다면 매우 쉬운일이다. 하지만 난 Rxjava의 함수를 이용해서 꼭하고 싶었다. 그래서 4일동안 map, flatMap, concatMap, flatMapSingle, just() 등등 있는 함수란 함수를 다 사용해서 시도 해봤다.
구조적은 어떻게 데이터를 내려야 해당 데이터가 바뀌고 내려올지, 어떤 데이터 타입을 반환해줄지, 진짜 내가 생각해 낼 수 있는 모든 것을 쥐어 짜서 수정하고 실행하고 결과 확인 하고를 다시 고치고를 3일동안 했다. 심지어 just()로 다시 데이터를 발행해서 다시 짜집기 해주는 것도 해봤다. 결국 안되었고 결국 4일째 나왔다.
해결...
정답은 의외로 간단했다. 심지어 시도해봤던 거였다. 바로 map()함수를 써서 변수로 수정된 데이터를 넣어주고 기존에 객체를 변경해주는 것이였다. 사실 이 방법도 썼었다. 처음에....
근데 왜 안나온 것일까...내 생각에는 map()을 사용할 때 다음에 내려주는 데이터를 잘 못했긴 때문인거 거 같다. 왜냐하면 map()이 해당 데이터를 변경해주는 함수인 것은 누구나 다 알고 있는 사실이다.
하지만 그러다 보니 map()를 사용해서 데이터를 변경해 주는 것까지는 잘하지만 만약에 해당 데이터를 감싸고 있는 데이터를 반환해 주어야 될 때 해당 반환값을 변경해서 주어야된다. 이부분이 잘못 된게 아닐까한다.
바로 이 아래의 별 부분이다.
바로 같다. 참 쉬운 부분이였는데....하....덕분에 배워간다.
[전제 코드 로직이다.] 일부러 주석도 남겨놓았다. 잊지 않기 위해서
(현재는 깔끔히 필요한 주석만 정리 했습니다.)
package com.example.lostproject.viewmodels
import android.util.Log
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import com.example.lostproject.base.BaseViewModel
import com.example.lostproject.network.managers.LostManager
import com.example.lostproject.network.models.dto.ChallengeAbyssDungeonResult
import com.example.lostproject.network.models.dto.ChallengeGuardianRaidResult
import com.example.lostproject.network.models.dto.ContentsCalendarResult
import com.example.lostproject.network.models.dto.RewardItemResult
import com.example.lostproject.util.Constants
import dagger.hilt.android.lifecycle.HiltViewModel
import io.reactivex.Observable
import io.reactivex.Single
import io.reactivex.rxkotlin.addTo
import io.reactivex.schedulers.Schedulers
import io.reactivex.subjects.PublishSubject
import java.text.SimpleDateFormat
import java.util.Date
import javax.inject.Inject
@HiltViewModel
class MainViewModel @Inject constructor(
private val lostManager: LostManager
) : BaseViewModel() {
private val _challengeAbyssDungeonList =
MutableLiveData<ArrayList<ChallengeAbyssDungeonResult>>()
val challengeAbyssDungeonList: LiveData<ArrayList<ChallengeAbyssDungeonResult>>
get() = _challengeAbyssDungeonList
private val _challengeGuardianRaid = MutableLiveData<ChallengeGuardianRaidResult>()
val challengeGuardianRaid: LiveData<ChallengeGuardianRaidResult>
get() = _challengeGuardianRaid
private val _contentsCalendarResultList = MutableLiveData<ArrayList<ContentsCalendarResult>>()
val contentsCalendarResultList: LiveData<ArrayList<ContentsCalendarResult>>
get() = _contentsCalendarResultList
private val _adventureIsland = MutableLiveData<ArrayList<ContentsCalendarResult>>()
val adventureIsland: LiveData<ArrayList<ContentsCalendarResult>>
get() = _adventureIsland
fun requestChallengeAbyssDungeons() {
lostManager.requestChallengeAbyssDungeons()
.subscribeOn(Schedulers.io())
.subscribe({
Log.e("cyc", "도전 어비스 던전 통신 성공")
_challengeAbyssDungeonList.postValue(it)
requestchallengeGuardianRaids()
}, {
Log.e("cyc", "도전 어비스 던전 통신 실패 : ${it}")
})
.addTo(disposable)
}
private fun requestchallengeGuardianRaids() {
lostManager.requestchallengeGuardianRaids()
.subscribeOn(Schedulers.io())
.subscribe({
Log.e("cyc", "도전 가디언 토벌 통신 성공")
_challengeGuardianRaid.postValue(it)
}, {
Log.e("cyc", "도전 가디언 토벌 통신 실패 : ${it}")
})
.addTo(disposable)
}
// 여기서 부터
//여기서 concat 써서 필터링하고 내려보기...아..
fun requestCalendar() {
val date = Date(System.currentTimeMillis())
val simpleDateFormat = SimpleDateFormat("yyyy-MM-dd")
val getDate = simpleDateFormat.format(date)
Log.e("cyc", "getDate--->${getDate}")
lostManager.requestCalendar()
.subscribeOn(Schedulers.io())
.map {
Log.e("cyc", "filterCalendar 전 ----it-->${it}")
it
}
.flatMap {
filterCalendar(it, getDate)
}
.map {
Log.e("cyc", "filterCalendar 후 ----it-->${it}")
it
}
.flatMap {
filterCalendarRewardItems(it, getDate)
}
.map {
Log.e("cyc", "filterCalendarRewardItems 후 ----it-->${it}")
it
}
.subscribe({
Log.e("cyc", "it-->${it}")
_contentsCalendarResultList.postValue(it as ArrayList<ContentsCalendarResult>)
requestIsland(it)
// Log.e("cyc","제발!!!! it--->${it}")
}, {
Log.e("cyc", "checkCalendar 실패 : ${it}")
})
.addTo(disposable)
}
private fun filterCalendar(
contentsCalendarResults: ArrayList<ContentsCalendarResult>,
getDate: String
): Single<ArrayList<ContentsCalendarResult>> {
return Observable.fromIterable(contentsCalendarResults)
.filter {
filterStartTimes(it.startTimes, getDate)
// it.startTimes.contains(getDate)
}.toList() as Single<ArrayList<ContentsCalendarResult>>
}
private fun filterCalendarRewardItems(
contentsCalendarResults: ArrayList<ContentsCalendarResult>,
getDate: String
): Single<ArrayList<ContentsCalendarResult>> {
return Observable.fromIterable(contentsCalendarResults)
.map {
Log.e("cyc", "filterCalendarRewardItems 내부 ----it-->${it}")
it
}
// .flatMap {
// Observable.fromIterable(it.rewardItems).filter { rewardItemResult ->
// filterStartTimes(rewardItemResult.startTimes,getDate)
// }
//// Log.e("cyc", "아이템보상 필터링된 후 값들 --->${it}")
//
// }
.map {
it.rewardItems = it.rewardItems.filter { rewardItemResult ->
filterStartTimes(rewardItemResult.startTimes,getDate)
} as ArrayList<RewardItemResult>
Log.e("cyc", "아이템보상 필터링된 후 값들 --->${it}")
it
}.toList() as Single<ArrayList<ContentsCalendarResult>>
// .flatMapSingle {
// testContentsCalendarResult(it,getDate)
// filterRewardItem(it.rewardItems, getDate)
// }.toList() as Single<ArrayList<ContentsCalendarResult>>
}
// private fun testContentsCalendarResult(
// contentsCalendarResult: ContentsCalendarResult,
// getDate: String
// ): Single<ArrayList<ContentsCalendarResult>>{
// return Observable.just(contentsCalendarResult)
// .map {
// Log.e("cyc", "testContentsCalendarResult 내부 ----it-->${it}")
// it
// }
// .map {
// it.rewardItems = filterRewardItem(it.rewardItems, getDate)
// it
// }.toList() as Single<ArrayList<ContentsCalendarResult>>
// }
// private fun testFilterRewardItem(
// contentsCalendarResult: ContentsCalendarResult,
// getDate: String
// ): ArrayList<RewardItemResult> {
// return Observable.fromIterable(contentsCalendarResult.rewardItems)
// .map {
// Log.e("cyc", "filterRewardItem 내부 ----it-->${it}")
// it
// }
// .filter {
// filterStartTimes(it.startTimes, getDate)
// // it.startTimes.contains(getDate)
// }.toList() as ArrayList<RewardItemResult>
// }
//
// private fun filterRewardItem(
// rewardItemResults: ArrayList<RewardItemResult>,
// getDate: String
// ): ArrayList<RewardItemResult> {
// return Observable.fromIterable(rewardItemResults)
// .map {
// Log.e("cyc", "filterRewardItem 내부 ----it-->${it}")
// it
// }
// .filter {
// filterStartTimes(it.startTimes, getDate)
//
// // it.startTimes.contains(getDate)
// }.toList() as ArrayList<RewardItemResult>
// }
private fun filterStartTimes(
startTimes: ArrayList<String>,
getDate: String
): Boolean {
Log.e("cyc","foreach문!!!!!")
Log.e("cyc","startTimes!!!!!---->${startTimes}")
val date = Date(System.currentTimeMillis())
val simpleDateFormat = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss")
val toDate = simpleDateFormat.format(date)
val strToDate = simpleDateFormat.parse(toDate)
var check = false
startTimes?.let {
it.forEach {str->
Log.e("cyc","str--나온값들---->${str}")
if (str.contains(getDate)) {
Log.e("cyc","str--> 같을때${str}")
Log.e("cyc","simpleDateFormat.parse(str)->${simpleDateFormat.parse(str)}")
Log.e("cyc","strToDate->${strToDate}")
if(simpleDateFormat.parse(str) >= strToDate){
Log.e("cyc","냥냥냥냥냥냥냥")
Log.e("cyc","")
check = true
}
}
}
}
return check
}
// private fun filterStartTimes(
// startTimes: ArrayList<String>,
// getDate: String
// ): Boolean {
// Log.e("cyc","foreach문!!!!!")
// Log.e("cyc","startTimes!!!!!---->${startTimes}")
// var check = false
// startTimes?.let {
//
// it.forEach {str->
// Log.e("cyc","str--나온값들---->${str}")
// if (str.contains(getDate)) {
// Log.e("cyc","str--> 같을때${str}")
// check = true
// }
// }
// }
//
// return check
// }
private fun requestIsland(contentsCalendarResults: ArrayList<ContentsCalendarResult>){
Single.just(contentsCalendarResults)
.subscribeOn(Schedulers.io())
.flatMap {
filterIsland(it)
}
.subscribe({
Log.e("cyc","requestIsland->${it}")
_adventureIsland.postValue(it)
}, {
Log.e("cyc", "adventure island 실패 : ${it}")
})
.addTo(disposable)
}
private fun filterIsland(
contentsCalendarResults: ArrayList<ContentsCalendarResult>
): Single<ArrayList<ContentsCalendarResult>>{
return Observable.fromIterable(contentsCalendarResults)
.filter {
it.categoryName == Constants.ADVENTURE_ISLAND
}.toList() as Single<ArrayList<ContentsCalendarResult>>
}
// fun requestCalendar() {
// val date = Date(System.currentTimeMillis())
// val simpleDateFormat = SimpleDateFormat("yyyy-MM-dd")
// val getDate = simpleDateFormat.format(date)
// lostManager.requestCalendar()
// .subscribeOn(Schedulers.io())
// .flatMap {
// filterAdventureIsland(it)
// }
// .toObservable()
//// .map {
//// Log.e("cyc", "모험섬 ContentsCalendarResult 필터 후 ----it-->${it}")
//// it
//// }
// .concatMapSingle {
// filterTodayAdventureIsland(it, getDate)
// }
//// .map {
//// Log.e("cyc", "모험섬 RewardItemResult 필터 후 ----it-->${it}")
//// it
//// }
// .subscribe({
//
// _adventureIsland.postValue(it)
// }, {
// Log.e("cyc", "checkCalendar 실패 : ${it}")
// })
// .addTo(disposable)
// }
//
// private fun filterAdventureIsland(
// contentsCalendarResults: ArrayList<ContentsCalendarResult>
// ): Single<ArrayList<ContentsCalendarResult>> {
// return Observable.fromIterable(contentsCalendarResults)
// .filter {
// it.categoryName == Constants.ADVENTURE_ISLAND
// }.toList() as Single<ArrayList<ContentsCalendarResult>>
// }
//
// private fun filterTodayAdventureIsland(
// contentsCalendarResults: ArrayList<ContentsCalendarResult>,
// getDate: String
// ): Single<ArrayList<ContentsCalendarResult>>{
// return Observable.fromIterable(contentsCalendarResults)
// .filter {
// filterStartTimes(it.startTimes,getDate)
// }
// .flatMap {
// filterTodayRewardItemResult(it.rewardItems, getDate)
// }.toList() as Single<ArrayList<ContentsCalendarResult>>
// }
//
//
// private fun filterTodayRewardItemResult(
// rewardItemResults: ArrayList<RewardItemResult>,
// getDate: String
// ): Observable<ArrayList<RewardItemResult>>{
// return Observable.fromIterable(rewardItemResults)
// .filter {
// filterStartTimes(it.startTimes,getDate)
// }.toList() as Observable<ArrayList<RewardItemResult>>
// }
//
// private fun filterStartTimes(
// startTimes: ArrayList<String>,
// getDate: String
// ): Boolean {
// var check = false
// startTimes.forEach {
// if (it.contains(getDate)) {
// check = true
// }
// }
// return check
// }
}
다시 Rxjava함수에 대해서 공부하고 다음에는 Subject 클래스의 대해서 알아보려고 한다.:)
'프로젝트 > LostArk 앱' 카테고리의 다른 글
이중 RecyclerView (0) | 2024.02.14 |
---|