Closed junseokseo9306 closed 2 years ago
LiveData 안에 MutableList 선언시 add 사용하면 발생하는 문제점
private val _homeContentsDetail = MutableLiveData<MutableList<Details>>()
val homeContentsDetail: LiveData<MutableList<Details>> = _homeContentsDetail
_homeContentsDetail.value.add( List )
위처럼 MutableLiveData 에서 setValue Add 메소드는 제대로 작동하지 않음.
@MainThread
protected void setValue(T value) {
assertMainThread("setValue");
mVersion++;
mData = value;
dispatchingValue(null);
}
위와 같은 방법으로 livedata는 버전관리를 하기 때문 참고 : 스타크 블로그
해결책
private val _yourRecommendProductsList: MutableList<YourRecommendProducts> = mutableListOf()
private val _yourRecommendProducts = MutableLiveData<MutableList<YourRecommendProducts>>()
val yourRecommendProducts: LiveData<MutableList<YourRecommendProducts>> = _yourRecommendProducts
_homeContentsDetailImage.value = _homeContentsDetailImageList
새로운 mutableList를 만들고 다시 liveData에 대입해 주는 방법을 사용
상황 : 사진과 타이틀은 각각 다른 API에 요청하여 가져오게 됨
문제 : 비동기로 이미지 처리시 이미지마다 요청시 각자의 이미지가 불러오는 순서가 뒤죽박죽이 되어 recyclerView에 사진과 이름이 다르게 가져오는 현상
for (i in 0 until homeContents.value?.yourRecommend?.products?.size!!) {
val job1 = async {
val yourRecommendProducts =
repository.loadStarbucksContents(homeContents.value?.yourRecommend?.products!![i].toLong())
yourRecommendProducts?.view?.let {
_homeContentsDetailList.add(it)
_homeContentsDetail.value = _homeContentsDetailList
.....
}
}
위의 이미지에서 볼 수 있듯이 이미지의 이름과 이미지가 다름을 알 수 있음
원인 : 기존 코드에서는 비동기 실행으로 바로바로 값을 가져오게 되니 이미지와 이름의 값이 먼저 요청의 답이 온 순서대로 list에 쌓이게됨
for (i in 0 until homeContents.value?.yourRecommend?.products?.size!!) {
val job1 = async {
val yourRecommendProducts =
repository.loadStarbucksContents(homeContents.value?.yourRecommend?.products!![i].toLong())
yourRecommendProducts?.view?.let {
_homeContentsDetailList.add(it)
_homeContentsDetail.value = _homeContentsDetailList
.....
}
}.await()
val contents = MutableList<Details>(1024) { null }
for (i in 0 until homeContents.value?.yourRecommend?.products?.size!!) {
val job1 = async {
val yourRecommendProducts =
repository.loadStarbucksContents(homeContents.value?.yourRecommend?.products!![i].toLong())
yourRecommendProducts?.view?.let {
contents[i] = it
.....
}
.awaitAll()
위와 같은 방식으로 contents[i] 의 순서를 강제하여 넣음 이렇게 되면 비동기적으로 작동하더라도 contents[i]의 위치를 알고 있기 때문에 비동기적으로 실행하여도 순서가 다르게 들어오지 않게됨.
상황 & 문제 : activity에서 viewModel을 사용하여 비동기 처리로 값을 받아왔지만 fragment에서는 값이 없다는 상황
기존 코드
private val viewModel: ViewModel by viewModels()
fragment에서 위와같이 새로운 viewModels() 호출
- 수정후
private val viewModel: ViewModel by activityViewModels()
이렇게 activityViewModels() 를 호출하면 액티비티와 프래그먼트간에 뷰 모델 공유 가능.
@BindingAdapter("string")
fun setColorTextView(view: TextView, text: String) {
val textLen = text.length
val subtitle = view.context.getString(R.string.your_recommend_title_example)
val spannable = SpannableStringBuilder(text)
spannable.append(subtitle)
spannable.setSpan(
ForegroundColorSpan(Color.RED),
0,
textLen,
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
)
view.text = spannable
}
SpannableStringBuilder 를 사용하여 Spannable 값을 지정해 줌 이렇게 하게 되면 특정 위치의 문자열만 색깔등 여러가지를 바꿀 수 있음
navigation attribute 속성의 pop Behavior
popUp to 설정 -> event fragment로 설정
popupInclusive -> true 로 설정
1.액션의 popUpTo 속성은 주어진 도착점(destination)이 나올 때까지 백 스택을 팝업한다.
Single Activity
Single Activity 싱글 액티비티는 하나의 액태비티를 두고 나머지 화면을 모두 프래그먼트로 구성하는 아키텍쳐로 Google I/O 2019 에서 Jetpack Navigation과 함께 소개
SignleActivity 의 장점