룬아님의 취중코딩

Koin을 이용하여 Fragment 끼리 ViewModel 공유하는 방법 본문

개발/안드로이드 개발

Koin을 이용하여 Fragment 끼리 ViewModel 공유하는 방법

룬아님 2020. 2. 6. 11:33

하나의 화면에 여러개의 Fragment가 있거나 뷰페이저를 사용할 때에도 비슷한 데이터를 사용해서 같은 뷰모델을 사용하여 데이터를 공유하고 싶을 때 사용할 수 있는 방법이다.

 

아래는 Viewpager2를 사용하여 Fragment에 MainViewModel을 공유하는 예시이다.

class MainViewModel(
    getUserEntityUseCase: GetUserEntityUseCase
    ) : ViewModel() {
    private val _userEntity = MutableLiveData(getUserEntityUseCase())
    val userEntity: LiveData<UserEntity?> = _userEntity

	....
    
}
val ApplicationModule = module {
   
    .....

    viewModel { MainViewModel(get()) }

    .....
}

위처럼 Koin module에 MainViewModel을 넣어주고

 

private const val NUM_PAGES = 2

class MainActivity : FragmentActivity() {
    /**
     * The pager widget, which handles animation and allows swiping horizontally to access previous
     * and next wizard steps.
     */

    val viewModel: MainViewModel by viewModel()

    private lateinit var viewPager: ViewPager2

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.main_activity)

        // Instantiate a ViewPager2 and a PagerAdapter.
        viewPager = findViewById(R.id.pager)
        viewPager.offscreenPageLimit = 2
        viewPager.isUserInputEnabled = false
        viewPager.setPageTransformer(ZoomOutPageTransformer())

        // The pager adapter, which provides the pages to the view pager widget.
        val pagerAdapter = ScreenSlidePagerAdapter(this)
        viewPager.adapter = pagerAdapter

        TabLayoutMediator(tabs, viewPager,
            TabLayoutMediator.TabConfigurationStrategy { tab, position ->
                when (position) {
                    0 -> { tab.text = "My Page"}
                    1 -> { tab.text = "History"}
                }
            }).attach()
    }

    override fun onBackPressed() {
        if (viewPager.currentItem == 0) {
            // If the userEntity is currently looking at the first step, allow the system to handle the
            // Back button. This calls finish() on this activity and pops the back stack.
            super.onBackPressed()
        } else {
            // Otherwise, select the previous step.
            viewPager.currentItem = viewPager.currentItem - 1
        }
    }

    /**
     * A simple pager adapter that represents 5 ScreenSlidePageFragment objects, in
     * sequence.
     */
    private inner class ScreenSlidePagerAdapter(fa: FragmentActivity) : FragmentStateAdapter(fa) {
        override fun getItemCount(): Int = NUM_PAGES

        override fun createFragment(position: Int): Fragment =
            when (position) {
                0 -> MyPageFragment()
                else -> SettingFragment()
            }
    }
}

by viewModel()을 통하여 viewModel 객체를 주입 받는다.

 

그 이후 해당 ViewModel이 필요한 Fragment에서

override val viewModel: MainViewModel by sharedViewModel()

by sharedViewModel()을 통하여 activity의 ViewModel을 받아올 수 있다.

그러면 activity와 sharedViewModel로 주입받은 fragment 모두 같은 ViewModel을 사용하기 때문에 데이터가 변하면 livedata를 통해 모든 뷰가 이벤트를 받을 수 있다.

 

참고 자료 : https://android.jlelse.eu/unlock-your-android-viewmodel-power-with-koin-23eda8f493be

 

Unlock your Android ViewModel power with Koin

Google has made a very nice gift with its Android Architecture Components. Now we have in hands tools and power to write more elegant and…

android.jlelse.eu

 

* viewModel은 Activity 혹은 Fragment에 연결되어 있다. 동일한 context를 사용한다면 sharedViewModel은 같은 viewmodel을 리턴해준다.

반응형
Comments