티스토리 뷰

Android/Kotlin

[Kotlin]  Activity와 Fragment 간의 ViewModel 공유

혀가 길지 않은 개발자 2020. 10. 5. 21:21

build.gradle (Module: app)

android {
    dataBinding {
        enabled = true
    }

    kotlinOptions {
        jvmTarget = "1.8"   // viewModels() 사용
    }
}

dependencies {
    // viewModels() 사용
    implementation 'androidx.fragment:fragment-ktx:1.2.5'
    // ViewPager2 사용
    implementation 'androidx.viewpager2:viewpager2:1.0.0'
}

 

 

 

 

 

 

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:app="http://schemas.android.com/apk/res-auto">
    <data>
        <variable
            name="viewModelActivity"
            type="com.jwsoft.kotlinproject.MainViewModel" />
    </data>

    <androidx.constraintlayout.widget.ConstraintLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MainActivity">

        <androidx.viewpager2.widget.ViewPager2
            android:id="@+id/viewPager"
            android:layout_marginBottom="80dp"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />


        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="80dp"
            android:gravity="center"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintBottom_toBottomOf="parent">

            <Button
                android:id="@+id/btnIncrease"
                android:layout_width="0dp"
                android:layout_height="80dp"
                android:layout_weight="1"
                android:text="Increase Activity ViewModel Count"
                android:textAllCaps="false"
                android:textSize="18dp"
                android:textStyle="italic"
                app:layout_constraintTop_toTopOf="parent"
                app:layout_constraintLeft_toLeftOf="parent"
                app:layout_constraintRight_toRightOf="parent"/>

        </LinearLayout>

    </androidx.constraintlayout.widget.ConstraintLayout>

</layout>

activity_main.xml

 

 

 

 

 

fragment_red.xml

<?xml version="1.0" encoding="utf-8"?>
<layout>
    <data>
        <variable
            name="viewModelActivity"
            type="com.jwsoft.kotlinproject.MainViewModel" />

        <variable
            name="viewModelFragment"
            type="com.jwsoft.kotlinproject.MainViewModel" />
    </data>

    <LinearLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        android:background="#FFBBBB"
        android:gravity="center">

        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" >

            <TextView
                android:text="Activity Count  :  "
                android:textSize="24dp"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"/>

            <TextView
                android:id="@+id/tvActivity"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="@{viewModelActivity.liveData.toString()}"
                android:textSize="26dp"
                android:textStyle="bold"/>

        </LinearLayout>

        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="10dp"
            android:gravity="center">

            <TextView
                android:text="Fragment Count  :  "
                android:textSize="24dp"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"/>

            <TextView
                android:id="@+id/tvFragment"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="@{viewModelFragment.liveData.toString()}"
                android:textSize="26dp"
                android:textStyle="bold"/>

        </LinearLayout>

        <Button
            android:id="@+id/btnIncrease"
            android:layout_width="match_parent"
            android:layout_height="80dp"
            android:layout_marginTop="10dp"
            android:layout_marginLeft="10dp"
            android:layout_marginRight="10dp"
            android:text="Increase Fragment ViewModel Count"
            android:textAllCaps="false"
            android:textSize="18dp"
            android:textStyle="italic"/>

    </LinearLayout>

</layout>

fragment_red.xml

 

 

 

 

 

fragment_green.xml

<?xml version="1.0" encoding="utf-8"?>
<layout>
    <data>
        <variable
            name="viewModelActivity"
            type="com.jwsoft.kotlinproject.MainViewModel" />

        <variable
            name="viewModelFragment"
            type="com.jwsoft.kotlinproject.MainViewModel" />
    </data>

    <LinearLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        android:background="#BBFFBB"
        android:gravity="center">

        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" >

            <TextView
                android:text="Activity Count  :  "
                android:textSize="24dp"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"/>

            <TextView
                android:id="@+id/tvActivity"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="@{viewModelActivity.liveData.toString()}"
                android:textSize="26dp"
                android:textStyle="bold"/>

        </LinearLayout>

        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="10dp"
            android:gravity="center">

            <TextView
                android:text="Fragment Count  :  "
                android:textSize="24dp"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"/>

            <TextView
                android:id="@+id/tvFragment"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="@{viewModelFragment.liveData.toString()}"
                android:textSize="26dp"
                android:textStyle="bold"/>

        </LinearLayout>

        <Button
            android:id="@+id/btnIncrease"
            android:layout_width="match_parent"
            android:layout_height="80dp"
            android:layout_marginTop="10dp"
            android:layout_marginLeft="10dp"
            android:layout_marginRight="10dp"
            android:text="Increase Fragment ViewModel Count"
            android:textAllCaps="false"
            android:textSize="18dp"
            android:textStyle="italic"/>

    </LinearLayout>

</layout>

fragment_green.xml

 

 

 

 

 

fragment_blue.xml

<?xml version="1.0" encoding="utf-8"?>
<layout>
    <data>
        <variable
            name="viewModelActivity"
            type="com.jwsoft.kotlinproject.MainViewModel" />

        <variable
            name="viewModelFragment"
            type="com.jwsoft.kotlinproject.MainViewModel" />
    </data>

    <LinearLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        android:background="#BBBBFF"
        android:gravity="center">

        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" >

            <TextView
                android:text="Activity Count  :  "
                android:textSize="24dp"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"/>

            <TextView
                android:id="@+id/tvActivity"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="@{viewModelActivity.liveData.toString()}"
                android:textSize="26dp"
                android:textStyle="bold"/>

        </LinearLayout>

        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="10dp"
            android:gravity="center">

            <TextView
                android:text="Fragment Count  :  "
                android:textSize="24dp"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"/>

            <TextView
                android:id="@+id/tvFragment"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="@{viewModelFragment.liveData.toString()}"
                android:textSize="26dp"
                android:textStyle="bold"/>

        </LinearLayout>

        <Button
            android:id="@+id/btnIncrease"
            android:layout_width="match_parent"
            android:layout_height="80dp"
            android:layout_marginTop="10dp"
            android:layout_marginLeft="10dp"
            android:layout_marginRight="10dp"
            android:text="Increase Fragment ViewModel Count"
            android:textAllCaps="false"
            android:textSize="18dp"
            android:textStyle="italic"/>

    </LinearLayout>

</layout>

fragment_blue.xml

 

 

 

fragment_white.xml

<?xml version="1.0" encoding="utf-8"?>
<layout>
    <data>
        <variable
            name="viewModelActivity"
            type="com.jwsoft.kotlinproject.MainViewModel" />

        <variable
            name="viewModelFragment"
            type="com.jwsoft.kotlinproject.MainViewModel" />
    </data>

    <LinearLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        android:background="#FFFFFF"
        android:gravity="center">

        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" >

            <TextView
                android:text="Activity Count  :  "
                android:textSize="24dp"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"/>

            <TextView
                android:id="@+id/tvActivity"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="@{viewModelActivity.liveData.toString()}"
                android:textSize="26dp"
                android:textStyle="bold"/>

        </LinearLayout>

        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="10dp"
            android:gravity="center">

            <TextView
                android:text="Fragment Count  :  "
                android:textSize="24dp"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"/>

            <TextView
                android:id="@+id/tvFragment"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="@{viewModelFragment.liveData.toString()}"
                android:textSize="26dp"
                android:textStyle="bold"/>

        </LinearLayout>

        <Button
            android:id="@+id/btnIncrease"
            android:layout_width="match_parent"
            android:layout_height="80dp"
            android:layout_marginTop="10dp"
            android:layout_marginLeft="10dp"
            android:layout_marginRight="10dp"
            android:text="Increase Fragment ViewModel Count"
            android:textAllCaps="false"
            android:textSize="18dp"
            android:textStyle="italic"/>

    </LinearLayout>

</layout>

fragment_white.xml

 

 

 

 

fragment_black.xml

<?xml version="1.0" encoding="utf-8"?>
<layout>
    <data>
        <variable
            name="viewModelActivity"
            type="com.jwsoft.kotlinproject.MainViewModel" />

        <variable
            name="viewModelFragment"
            type="com.jwsoft.kotlinproject.MainViewModel" />
    </data>

    <LinearLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        android:background="#000000"
        android:gravity="center">

        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" >

            <TextView
                android:text="Activity Count  :  "
                android:textSize="24dp"
                android:textColor="#FFFFFF"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"/>

            <TextView
                android:id="@+id/tvActivity"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="@{viewModelActivity.liveData.toString()}"
                android:textSize="26dp"
                android:textColor="#FFFFFF"
                android:textStyle="bold"/>

        </LinearLayout>

        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="10dp"
            android:gravity="center">

            <TextView
                android:text="Fragment Count  :  "
                android:textSize="24dp"
                android:textColor="#FFFFFF"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"/>

            <TextView
                android:id="@+id/tvFragment"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="@{viewModelFragment.liveData.toString()}"
                android:textColor="#FFFFFF"
                android:textSize="26dp"
                android:textStyle="bold"/>

        </LinearLayout>

        <Button
            android:id="@+id/btnIncrease"
            android:layout_width="match_parent"
            android:layout_height="80dp"
            android:layout_marginTop="10dp"
            android:layout_marginLeft="10dp"
            android:layout_marginRight="10dp"
            android:text="Increase Fragment ViewModel Count"
            android:textAllCaps="false"
            android:textSize="18dp"
            android:textStyle="italic"/>

    </LinearLayout>

</layout>

fragment_black.xml

 

 

 

 

MainViewModel.kt

package com.jwsoft.kotlinproject

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

class MainViewModel : ViewModel() {

    var liveData: MutableLiveData<Int> = MutableLiveData()

    init {
        liveData.value = 0
    }

}

 

 

 

 

FragmentRed.kt

package com.jwsoft.kotlinproject

import android.content.Context
import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.databinding.DataBindingUtil
import androidx.fragment.app.Fragment
import androidx.lifecycle.ViewModelProvider
import com.jwsoft.kotlinproject.databinding.FragmentRedBinding
import kotlinx.android.synthetic.main.fragment_red.*

class FragmentRed : Fragment() {

    lateinit var binding: FragmentRedBinding
    lateinit var viewModelActivity: MainViewModel
    lateinit var viewModelFragment: MainViewModel

    override fun onAttach(context: Context) {
        super.onAttach(context)
        Log.e("", "Red - onAttach")
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        Log.e("", "Red - onCreate")
    }

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        Log.e("", "Red - onCreateView")
        binding = DataBindingUtil.inflate(inflater, R.layout.fragment_red, container, false)
        binding.lifecycleOwner = this

        viewModelActivity = activity?.let { ViewModelProvider(it, ViewModelProvider.NewInstanceFactory()).get(MainViewModel::class.java) }!!
        viewModelFragment = ViewModelProvider(this, ViewModelProvider.NewInstanceFactory()).get(MainViewModel::class.java)
        binding.viewModelActivity = viewModelActivity
        binding.viewModelFragment = viewModelFragment

        return binding.root
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        Log.e("", "Red - onViewCreated")

        btnIncrease.setOnClickListener {
            viewModelFragment.liveData.postValue(viewModelFragment.liveData.value!!.plus(1))
        }
    }

    override fun onActivityCreated(savedInstanceState: Bundle?) {
        super.onActivityCreated(savedInstanceState)
        Log.e("", "Red - onActivityCreated")
    }

    override fun onStart() {
        super.onStart()
        Log.e("", "Red - onStart")
    }

    override fun onResume() {
        super.onResume()
        Log.e("", "Red - onResume")
    }

    override fun onPause() {
        super.onPause()
        Log.e("", "Red - onPause")
    }

    override fun onStop() {
        super.onStop()
        Log.e("", "Red - onStop")
    }

    override fun onDestroyView() {
        super.onDestroyView()
        Log.e("", "Red - onDestroyView")
    }

    override fun onDestroy() {
        super.onDestroy()
        Log.e("", "Red - onDestroy")
    }

    override fun onDetach() {
        super.onDetach()
        Log.e("", "Red - onDetach")
    }

}

ViewModel 객체 생성 시 fragment-ktx를 이용하여 간편하게 생성할 수 있다.

private val viewModelActivity: MainViewModel by activityViewModels()

private val viewModelFragment: MainViewModel by viewModels()

 

 

 

 

FragmentGreen.kt

package com.jwsoft.kotlinproject

import android.content.Context
import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.databinding.DataBindingUtil
import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels
import androidx.fragment.app.viewModels
import com.jwsoft.kotlinproject.databinding.FragmentGreenBinding
import kotlinx.android.synthetic.main.fragment_green.btnIncrease

class FragmentGreen: Fragment() {

    lateinit var binding: FragmentGreenBinding
    private val viewModelFragment: MainViewModel by viewModels()
    private val viewModelActivity: MainViewModel by activityViewModels()

    override fun onAttach(context: Context) {
        super.onAttach(context)
        Log.e("", "Green - onAttach")
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        Log.e("", "Green - onCreate")
    }

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        Log.e("", "Green - onCreateView")
        binding = DataBindingUtil.inflate(inflater, R.layout.fragment_green, container, false)
        binding.lifecycleOwner = this
        binding.viewModelActivity = viewModelActivity
        binding.viewModelFragment = viewModelFragment

        return binding.root
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        Log.e("", "Green - onViewCreated")

        btnIncrease.setOnClickListener {
            viewModelFragment.liveData.postValue(viewModelFragment.liveData.value!!.plus(1))
        }
    }

    override fun onActivityCreated(savedInstanceState: Bundle?) {
        super.onActivityCreated(savedInstanceState)
        Log.e("", "Green - onActivityCreated")
    }

    override fun onStart() {
        super.onStart()
        Log.e("", "Green - onStart")
    }

    override fun onResume() {
        super.onResume()
        Log.e("", "Green - onResume")
    }

    override fun onPause() {
        super.onPause()
        Log.e("", "Green - onPause")
    }

    override fun onStop() {
        super.onStop()
        Log.e("", "Green - onStop")
    }

    override fun onDestroyView() {
        super.onDestroyView()
        Log.e("", "Green - onDestroyView")
    }

    override fun onDestroy() {
        super.onDestroy()
        Log.e("", "Green - onDestroy")
    }

    override fun onDetach() {
        super.onDetach()
        Log.e("", "Green - onDetach")
    }

}

 

 

 

 

 

FragmentBlue.kt

package com.jwsoft.kotlinproject

import android.content.Context
import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.databinding.DataBindingUtil
import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels
import androidx.fragment.app.viewModels
import com.jwsoft.kotlinproject.databinding.FragmentBlueBinding
import kotlinx.android.synthetic.main.fragment_blue.*

class FragmentBlue : Fragment() {

    lateinit var binding: FragmentBlueBinding
    private val viewModelActivity: MainViewModel by activityViewModels()
    private val viewModelFragment: MainViewModel by viewModels()

    override fun onAttach(context: Context) {
        super.onAttach(context)
        Log.e("", "Blue - onAttach")
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        Log.e("", "Blue - onCreate")
    }

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        Log.e("", "Blue - onCreateView")
        binding = DataBindingUtil.inflate(inflater, R.layout.fragment_blue, container, false)
        binding.lifecycleOwner = this
        binding.viewModelActivity = viewModelActivity
        binding.viewModelFragment = viewModelFragment

        return binding.root
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        Log.e("", "Blue - onViewCreated")

        btnIncrease.setOnClickListener {
            viewModelFragment.liveData.postValue(viewModelFragment.liveData.value!!.plus(1))
        }
    }

    override fun onActivityCreated(savedInstanceState: Bundle?) {
        super.onActivityCreated(savedInstanceState)
        Log.e("", "Blue - onActivityCreated")
    }

    override fun onStart() {
        super.onStart()
        Log.e("", "Blue - onStart")
    }

    override fun onResume() {
        super.onResume()
        Log.e("", "Blue - onResume")
    }

    override fun onPause() {
        super.onPause()
        Log.e("", "Blue - onPause")
    }

    override fun onStop() {
        super.onStop()
        Log.e("", "Blue - onStop")
    }

    override fun onDestroyView() {
        super.onDestroyView()
        Log.e("", "Blue - onDestroyView")
    }

    override fun onDestroy() {
        super.onDestroy()
        Log.e("", "Blue - onDestroy")
    }

    override fun onDetach() {
        super.onDetach()
        Log.e("", "Blue - onDetach")
    }
}

 

 

 

 

 

FragmentWhite.kt

package com.jwsoft.kotlinproject

import android.content.Context
import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.databinding.DataBindingUtil
import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels
import androidx.fragment.app.viewModels
import com.jwsoft.kotlinproject.databinding.FragmentWhiteBinding
import kotlinx.android.synthetic.main.fragment_white.*

class FragmentWhite : Fragment() {

    lateinit var binding: FragmentWhiteBinding
    private val viewModelActivity: MainViewModel by activityViewModels()
    private val viewModelFragment: MainViewModel by viewModels()

    override fun onAttach(context: Context) {
        super.onAttach(context)
        Log.e("", "White - onAttach")
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        Log.e("", "White - onCreate")
    }

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        Log.e("", "White - onCreateView")
        binding = DataBindingUtil.inflate(inflater, R.layout.fragment_white, container, false)
        binding.lifecycleOwner = this
        binding.viewModelActivity = viewModelActivity
        binding.viewModelFragment = viewModelFragment

        return binding.root
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        Log.e("", "White - onViewCreated")

        btnIncrease.setOnClickListener {
            viewModelFragment.liveData.postValue(viewModelFragment.liveData.value!!.plus(1))
        }
    }

    override fun onActivityCreated(savedInstanceState: Bundle?) {
        super.onActivityCreated(savedInstanceState)
        Log.e("", "White - onActivityCreated")
    }

    override fun onStart() {
        super.onStart()
        Log.e("", "White - onStart")
    }

    override fun onResume() {
        super.onResume()
        Log.e("", "White - onResume")
    }

    override fun onPause() {
        super.onPause()
        Log.e("", "White - onPause")
    }

    override fun onStop() {
        super.onStop()
        Log.e("", "White - onStop")
    }

    override fun onDestroyView() {
        super.onDestroyView()
        Log.e("", "White - onDestroyView")
    }

    override fun onDestroy() {
        super.onDestroy()
        Log.e("", "White - onDestroy")
    }

    override fun onDetach() {
        super.onDetach()
        Log.e("", "White - onDetach")
    }

}

 

 

 

 

 

FragmentBlack.kt

package com.jwsoft.kotlinproject

import android.content.Context
import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.databinding.DataBindingUtil
import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels
import androidx.fragment.app.viewModels
import com.jwsoft.kotlinproject.databinding.FragmentBlackBinding
import kotlinx.android.synthetic.main.fragment_black.*

class FragmentBlack : Fragment() {

    lateinit var binding: FragmentBlackBinding
    private val viewModelActivity: MainViewModel by activityViewModels()
    private val viewModelFragment: MainViewModel by viewModels()

    override fun onAttach(context: Context) {
        super.onAttach(context)
        Log.e("", "Black - onAttach")
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        Log.e("", "Black - onCreate")
    }

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        Log.e("", "Black - onCreateView")
        binding = DataBindingUtil.inflate(inflater, R.layout.fragment_black, container, false)
        binding.lifecycleOwner = this
        binding.viewModelActivity = viewModelActivity
        binding.viewModelFragment = viewModelFragment

        return binding.root
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        Log.e("", "Black - onViewCreated")

        btnIncrease.setOnClickListener {
            viewModelFragment.liveData.postValue(viewModelFragment.liveData.value!!.plus(1))
        }
    }

    override fun onActivityCreated(savedInstanceState: Bundle?) {
        super.onActivityCreated(savedInstanceState)
        Log.e("", "Black - onActivityCreated")
    }

    override fun onStart() {
        super.onStart()
        Log.e("", "Black - onStart")
    }

    override fun onResume() {
        super.onResume()
        Log.e("", "Black - onResume")
    }

    override fun onPause() {
        super.onPause()
        Log.e("", "Black - onPause")
    }

    override fun onStop() {
        super.onStop()
        Log.e("", "Black - onStop")
    }

    override fun onDestroyView() {
        super.onDestroyView()
        Log.e("", "Black - onDestroyView")
    }

    override fun onDestroy() {
        super.onDestroy()
        Log.e("", "Black - onDestroy")
    }

    override fun onDetach() {
        super.onDetach()
        Log.e("", "Black - onDetach")
    }

}

 

 

 

 

 

FragmentAdapter.kt

package com.jwsoft.kotlinproject

import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentActivity
import androidx.viewpager2.adapter.FragmentStateAdapter

class FragmentAdapter(fragmentActivity: FragmentActivity)
    : FragmentStateAdapter(fragmentActivity) {

    override fun createFragment(position: Int): Fragment {
        return when (position) {
            0 -> FragmentRed()
            1 -> FragmentGreen()
            2 -> FragmentBlue()
            3 -> FragmentWhite()
            4 -> FragmentBlack()
            else -> FragmentRed()
        }
    }

    override fun getItemCount(): Int = 5

}

 

 

 

 

 

MainActivity.kt

package com.jwsoft.kotlinproject

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import androidx.activity.viewModels
import androidx.databinding.DataBindingUtil
import androidx.viewpager2.widget.ViewPager2
import com.jwsoft.kotlinproject.databinding.ActivityMainBinding
import kotlinx.android.synthetic.main.activity_main.*

class MainActivity : AppCompatActivity() {

    private lateinit var binding: ActivityMainBinding
    private val viewModel: MainViewModel by viewModels()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        Log.e("", "Activity - onCreate")

        binding = DataBindingUtil.setContentView(this, R.layout.activity_main)
        binding.lifecycleOwner = this
        binding.viewModelActivity = viewModel

        viewPager.adapter = FragmentAdapter(this)
        viewPager.orientation = ViewPager2.ORIENTATION_HORIZONTAL

        btnIncrease.setOnClickListener {
            viewModel.liveData.postValue(viewModel.liveData.value!!.plus(1))
        }

    }

    override fun onStart() {
        super.onStart()
        Log.e("", "Activity - onStart")
    }

    override fun onResume() {
        super.onResume()
        Log.e("", "Activity - onResume")
    }

    override fun onPause() {
        super.onPause()
        Log.e("", "Activity - onPause")
    }

    override fun onStop() {
        super.onStop()
        Log.e("", "Activity - onStop")
    }

    override fun onDestroy() {
        super.onDestroy()
        Log.e("", "Activity - onDestroy")
    }

}

실행 결과

 

 

Red 페이지와 Black 페이지의 Count가 초기화된 이유는

ViewPager2의 페이지 보존 속성(ViewPager2.offscreenPageLimit)을 설정하지 않으면

일정 페이지를 벗어났을 때 리미트를 초과한 Fragment는 파괴되고

해당 Fragment의 생명주기를 가진 ViewModel도 onCleared() 되기 때문이다.

 

 

 

 

댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/12   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31
글 보관함