View와 ViewModel

핑구·2022년 10월 1일
0

ViewModel이란?

공식 문서
공식 예시 블로그
The ViewModel class is designed to hold and manage UI-related data in a life-cycle conscious way. This allows data to survive configuration changes such as screen rotations.

  • 생명주기 관리가 쉽고 lifeCycle에 따라서 UI 데이터 관리가 용이하다.
    → 화면 회전(핸드폰 옆으로)과 같은 변화에도 데이터를 보존할 수 있다.
  • UI컨트롤러(Activity, Fragment)에서 모든 것을 다 하려고 하면 복잡
    → ViewModel을 사용해 테스트와 관리를 쉽게 할 수 있다.

자세히 설명해 준 블로그

Activity에서 ViewModel 사용

MainActivity.kt

class MainActivity : AppCompatActivity() {

    lateinit var viewModel: MainViewModel

    override fun onCreate(savedInstanceState: Bundle?) {

        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        viewModel = ViewModelProvider(this).get(MainViewModel::class.java)

        val plusBtn : Button = findViewById(R.id.plus)
        val minusBtn : Button = findViewById(R.id.minus)

        val resultArea : TextView = findViewById(R.id.result)

        resultArea.text= viewModel.getCount().toString()

        plusBtn.setOnClickListener{
			viewModel.plus()
            resultArea.text= viewModel.getCount().toString()
		}

		minusBtn.setOnClickListener{
			viewModel.minus()
            resultArea.text= viewModel.getCount().toString()
		}	
    }
}

ViewModelProvider로 MainViewModel을 불러와 viewModel 인스턴스를 만든다.
viewModel의 함수를 이용하여 값은 더하거나 빼준다.

MainViewModel.kt

class MainViewModel : ViewModel() {

    var countValue = 0

    init {
        Log.d("MainViewModel", "init")
    }

    fun plus(){
        countValue++
    }

    fun minus(){
        countValue--
    }

    fun getCount() : Int {
        return countValue
    }

}

Activity뿐만 아니라 Fragment에서도 동일한 방식으로 ViewModel을 이용할 수 있다.

Activity / Fragment의 ViewModel 공유

Activity의 값을 Fragment에서 쓰고 싶거나, Fragment에서 값을 ViewModel의 값으로 사용하기 위해 이 기능을 이용한다.

동일한 ViewModel을 사용하여 공유할 수 있다.

MainActivity.kt

class MainActivity : AppCompatActivity() {

    lateinit var binding : ActivityMainBinding
    lateinit var viewModel : MainViewModel

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

        binding = DataBindingUtil.setContentView(this,R.layout.activity_main)
        viewModel = ViewModelProvider(this).get(MainViewModel::class.java)

        binding.resultArea.text = viewModel.getCount().toString()

        binding.plus.setOnClickListener {
            viewModel.plus()
            binding.resultArea.text = viewModel.getCount().toString()
        }

        binding.minus.setOnClickListener {
            viewModel.minus()
            binding.resultArea.text = viewModel.getCount().toString()
        }

        val manager = supportFragmentManager

        binding.showFragment.setOnClickListener {
            val transaction = manager.beginTransaction()
            val fragment = TestFragment()
            transaction.replace(R.id.frameArea, fragment)
            transaction.addToBackStack(null)
            transaction.commit()
        }

    }
}

TestFragment.kt

class TestFragment : Fragment() {

    private lateinit var binding : FragmentTestBinding
    private val viewModel : MainViewModel by activityViewModels()

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

    }

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?,
    ): View? {
        // Inflate the layout for this fragment

        binding = DataBindingUtil.inflate(inflater, R.layout.fragment_test, container, false)

        binding.fragmentTest.text = viewModel.getCount().toString()

        return binding.root
    }

}

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<layout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools">

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MainActivity">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical">

            <TextView
                android:id="@+id/resultArea"
                android:text="0"
                android:textSize="50sp"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"/>

            <Button
                android:id="@+id/plus"
                android:text="plus"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"/>

            <Button
                android:id="@+id/minus"
                android:text="minus"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"/>

            <Button
                android:id="@+id/showFragment"
                android:text="showFragment"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"/>

            <FrameLayout
                android:id="@+id/frameArea"
                android:background="#32a852"
                android:layout_width="match_parent"
                android:layout_height="200dp"/>
        </LinearLayout>
    </androidx.constraintlayout.widget.ConstraintLayout>
</layout>
profile
발전중

0개의 댓글