안드로이드개발

[Kotlin] ViewModel, Livedata 로 Fragment 끼리 통신하기

아뵹젼 2022. 1. 21.

구현할 Fragment 및 화면 구조

내가 구성한 화면은 친구목록이라는 Fragment 안에 Tablayout 을 사용하고,

내부는 Viewpager2 를 이용해 찜한 친구와 지난 추천 친구라는 Fragment 를 배치한 구조이다.

 

친구목록[Fragment]

  • 찜한 친구[Fragment]
  • 지난 추천 친구[Fragment]

로 구성된 구조이다.

 

찜한 친구는 recyclerview 로 구현했는데,

친구를 삭제할 때마다 (adapter listener 를 통해) 친구 목록 Fragment 의 Tab text [ -> 찜한 친구(8) ]가 동적으로 변하는 것을 구현해야 했다.

 

 

원래 구현하려 했던 방법 (기본 방법)

  • 찜한 친구 Fragment 에서 adapter listener 를 통해 친구목록에 변화가 감지되면, MainActivity 에 인터페이스 함수를 구현하고, 그 함수 내부에서 친구 목록 Fragment 의 함수를 호출해서, 친구 목록 Fragment 함수 내부에서 tab text 를 변경해주는 로직이다.
  • 그러나, MainActivity 에서 interface 를 구현하고 불필요한 함수를 만드는 것이 비효율적이라고 생각해서
  • 이참에 사용해보고 싶었지만 진입장벽이 높게 느껴져 시도해 보지 못했던 ViewModel 을 사용해 보기로 했다.
  • ViewModel 안에 있는 LiveData 객체를 DataBinding을 통해 UI에서 관찰만 한다면 (observe 사용) , 액티비티나 프래그먼트에서 일일히 데이터를 갱신할 필요 없이 알아서 UI에 최신 데이터가 보이는 것이 매우 효율적으로 느껴졌기 때문이다.

 

ViewModel Class 생성

import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel


class FriendListCountViewModel : ViewModel() {

    // 내부에서 설정하는 자료형은 Mutable 로 변경가능하도록 설정
    private val _currentCount = MutableLiveData<Int>()


    // 데이터를 직접 접근하지 않고 뷰모델을 통해 가져올 수 있도록 설정
    val currentCount: LiveData<Int>
        get() = _currentCount

    // 초기값 설정
    init {
        _currentCount.value = 0
    }

    fun updateValue(count: Int){
        _currentCount.value = count
    }

}

 

 

찜한 친구 목록 Fragment

starredFriendListRVAdapter.setMyItemClickListener(object : StarredFriendListRVAdapter.MyItemClickListener{
    override fun onDeleteFriend(friendId: String) {
        // 찜한친구 목록에서 삭제
    }

    override fun onGetFriendCount() {
        // 뷰 모델 프로바이더를 통해 뷰모델 가져오기
        sharedViewModel = ViewModelProvider(requireActivity()).get(FriendListCountViewModel::class.java)
        // 라이브 데이터 값 변경
        sharedViewModel.updateValue(starredFriendListRVAdapter.itemCount)
    }
})
binding.starredFriendListRecyclerviewRc.adapter = starredFriendListRVAdapter

adapter 에서 친구 삭제 이벤트가 발생하면, 뷰 모델의 라이브 데이터 값을 변경한다.

 

 

 

친구 목록 Fragment

override fun initAfterBinding() {
    var friendCount : Int // 서버에서 친구 수 받아오기

    val friendListViewpagerAdapter = FriendListViewpagerAdapter(this)
    binding.friendListContentVp.adapter = friendListViewpagerAdapter

    val child = binding.friendListContentVp.getChildAt(0)
    (child as RecyclerView)?.overScrollMode = View.OVER_SCROLL_NEVER

    sharedViewModel = ViewModelProvider(requireActivity()).get(FriendListCountViewModel::class.java)
    sharedViewModel.currentCount.observe(this, Observer {
        friendCount = it
        TabLayoutMediator(binding.friendListContentTb, binding.friendListContentVp){
                tab, position -> tab.text =  arrayListOf("찜한 친구($friendCount)", "지난 추천 친구")[position]
        }.attach()
    })
}

뷰모델을 통해 ui 를 관찰하면서 변경된 라이브 데이터 값을 tab text 에 설정하였다.

댓글