잘 모르겠고, 바로 적용부터 해보자
이번에 해볼것은
1
1) 식별자를 통해서 그 사람의 정보와, 사진을 파이어베이스에서 받아오고
2). 그걸 viewmodel에 적용후
3) 프래그먼트에 쏴주기
2
1) 식별자 통해서 그 사람의 정보 얻고
2) 정보를 얻은 후에 정보내의 데이터를 이용하여 사진을 파이어베이스에서 받기
3) 4) view까지 연결
우선 첫번째 과제부터 시작해보자!
우선 레포에서 파이어베이스와 연결하여 uid로만 데이터를 가져오는 코드를 짠다.
@Singleton
class TestRepo @Inject constructor() {
val firebase = FirebaseFirestore.getInstance()
val firestorage = FirebaseStorage.getInstance()
//데이터 , 사진URI 페어로 넘겨야겠다
suspend fun getPersonInfo(uid: String): Pair<CardInfo?, Uri?> {
return withContext(Dispatchers.IO) { // 코루틴생성
val pic = async { (getUserPicture(uid)) } // 비동기로 사진 가져오기
val card = async { getUserTextInfo(uid) } // 비동기로 정보 가져오기
card.await() to pic.await() // 둘다 기다리고 반환하기
}
}
suspend fun getUserTextInfo(uid: String) = coroutineScope{
println("start getText")
var a: CardInfo? = null
firebase.collection("data").document(uid).get().addOnSuccessListener {
a = it.toCardInfoMaker(0)
}.addOnFailureListener {
}.await()
val b = 9
println("end getText")
a
}
suspend fun getUserPicture(uid: String) = coroutineScope{
println("start getPic")
var a: Uri? = null
var doc: StorageReference? = null
firestorage.reference.child("data/$uid/thumbnail/").list(1)
.addOnSuccessListener {
doc = it.items[0]
it.items[0]
}.await() // 기다리기
doc?.let { s ->
s.downloadUrl.addOnSuccessListener {
a = it // 다운로드
}.await() // 기다리기
}
println("end getPic")
a
}
}
이 요청을 뷰모델에서 뷰모델의 라이브 데이터에 업데이트 시켜준다!.
@HiltViewModel
class TestViewModel @Inject constructor( val repo : TestRepo) :ViewModel() {
val info = MutableLiveData<CardInfo?>()
val pic = MutableLiveData<Uri?>()
private fun setInfo(ci :CardInfo?){
ci?.let{
info.value = it
}
}
private fun setPic(ci :Uri?){
ci?.let{
pic.value = it
}
}
fun getPerson(id: String){
viewModelScope.launch {
val result = repo.getPersonInfo(id)
setInfo(result.first)
setPic(result.second)
println("final : ${Thread.currentThread().name}")
}
}
}
그럼 이 뷰모델에 들어있는 라이브데이터를 옵버블 패턴으로 뷰에서 변화시켜준다
Fragment 입니다!
viewModel.info.observe(viewLifecycleOwner){
Toast.makeText(requireContext(),"$it",Toast.LENGTH_SHORT).show()
}
viewModel.pic.observe(viewLifecycleOwner){
it?.let{
val picAdapter = M2CardDetailImgAdapter(listOf(it))
binding.bCardDetailVpIndicator.createDotPanel(
1,
R.drawable.indicator_off,
R.drawable.indicator_on,
0
)// 뷰페이저로 되있어서 .. 귀찮아서 있던거 그대로 씀..
binding.bCardDetailNsv1Clo1VpImg.adapter = picAdapter
}
}
// 출력내용
//I/System.out: start getText : DefaultDispatcher-worker-2
//I/System.out: start getPic : DefaultDispatcher-worker-3
//I/System.out: end getText : DefaultDispatcher-worker-3
//I/System.out: end getPic : DefaultDispatcher-worker-3
두번째는 레포지토리만 변경해서 쓰자!
suspend fun getPersonInfo(uid: String): Pair<CardInfo?, Uri?> {
return withContext(Dispatchers.IO) {
val card = getUserTextInfo(uid)
val pic = async { (getUserPicture(card!!.fid)) }
card to pic.await()
}
}
suspend fun getUserTextInfo(uid: String) = coroutineScope{
withContext(Dispatchers.Default) {
println("start getText : ${Thread.currentThread().name}")
var a: CardInfo? = null
firebase.collection("data").document(uid).get().addOnSuccessListener {
a = it.toCardInfoMaker(0)
}.addOnFailureListener {
}.await()
println("end getText : ${Thread.currentThread().name}")
a
}
}
//다른 코드는 동일함
//출력
//I/System.out: start getText : DefaultDispatcher-worker-1
//I/System.out: end getText : DefaultDispatcher-worker-1
//I/System.out: start getPic : DefaultDispatcher-worker-1
//I/System.out: end getPic : DefaultDispatcher-worker-1
위의 경우도 동일한 결과가 나온다!
'코틀린 > Coroutine' 카테고리의 다른 글
코틀린의 Companion object 사용?Volatile? (2022.7.21) (0) | 2022.07.21 |
---|---|
Android Coroutine (4) (0) | 2021.11.26 |
Android Coroutine (3) 콜백과 비교해보기 (0) | 2021.11.26 |
Android Coroutine 기본 (0) | 2021.11.25 |