티스토리 뷰

Android

[Android] ViewModel

DDunTory 2021. 3. 6. 15:34

Configuration이 destroy 될 때

 

1. Rotation (portrait <-> landscape)
2. keyboard changes
3. language changes
4. enabling multiwindow

   .....

 

ViewModel 생명주기

 

 

  • ViewModel은 ViewModel은 하나의 액티비티, 프래그먼트 혹은 여러개 액티비티, 프래그먼트에 연동됩니다.
  • ViewModel은 액티비티나 프래그먼트의 생명주기동안 살아있다가 Finished 될 때, onCleared() 됩니다.
  • AndroidViewModel vs ViewModel : AndroidViewModel은 memory leak가 발생할 수 있지만 Context를 사용해야 할 때 쓰며, 이 외 상황에서는 개발문서에서도 ViewModel을 쓰도록 권장합니다.
  • ViewModel이 onCleared() 될 때 : 앱이 백그라운드로 넘어가거나 시스템 메모리 free 되면서 프로세스가 죽을 때 압니다. 

ViewModel 요청 프로세스

 

 

  1. ViewModelProvider를 통해 ViewModel 인스턴스를 요청합니다.

  2. ViewModelProvider 내부에서는 ViewModelStoreOwner를 참조하여 ViewModelStore를 가져옵니다.

  3. ViewModelStore에게 이미 생성된(저장된) ViewModel 인스턴스를 요청합니다.

  4. 만약 ViewModelStore가 적합한 ViewModel 인스턴스를 가지고 있지 않다면, Factory를 통해 ViewModel인스턴스를 생성합니다.

  5. 생성한 ViewModel 인스턴스를 ViewModeStore에 저장하고 만들어진 ViewModel 인스턴스를 클라이언트에게 반환합니다.

  6. 똑같은 ViewModel 인스턴스 요청이 들어온다면, 1~3번의 과정을 반복하게 됩니다.

ViewModel 요청 프로세스 출처 : charlezz.medium.com/viewmodel%EC%9D%B4%EB%9E%80-%EB%AC%B4%EC%97%87%EC%9D%B8%EA%B0%80-viewmodel-%EC%B4%88%EB%B3%B4%EB%A5%BC-%EC%9C%84%ED%95%9C-%EA%B0%80%EC%9D%B4%EB%93%9C-e1be5dc1ac18

 

ViewModel이란 무엇인가? ViewModel 초보를 위한 가이드

ViewModel이란?

charlezz.medium.com

 

ViewModel 실습

 

MainActivity

class MainActivity: AppCompatActivity() {
    private lateinit var binding: ActivityMainBinding
    private lateinit var viewModel: MainActivityViewModel

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

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

        binding.countText.text=viewModel.getCurrentCount().toString()

        binding.button.setOnClickListener {
            binding.countText.text=viewModel.getUpdatedCount().toString()
        }
        binding.intentButton.setOnClickListener {
            startActivity(Intent(this, SecondActivity::class.java))
        }
    }
}

 

MainActivityViewModel

class MainActivityViewModel: ViewModel() {
    private var count = 0

    fun getCurrentCount():Int{
        return count
    }

    fun getUpdatedCount():Int{
        return ++count
    }
}

 

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">

        <TextView
            android:id="@+id/count_text"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textSize="66sp"
            android:textStyle="bold"
            android:typeface="serif"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintHorizontal_bias="0.5"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintVertical_bias="0.262" />

        <Button
            android:id="@+id/button"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Click Here"
            android:textSize="30sp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintHorizontal_bias="0.5"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

        <Button
            android:id="@+id/intent_button"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginBottom="92dp"
            android:text="다음"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent" />

    </androidx.constraintlayout.widget.ConstraintLayout>
</layout>

 

main_activity 화면

 

 

설명

 

"CLICK HERE" 버튼을 누르면 1씩 count가 증가하여 표시됩니다.

Rotation을 하면 Configuration이 destroy 되어야 하는데, ViewModel로 observe하고 있기 때문에, count 된 숫자는 그대로 유지됩니다. 

 

 

SecondActivity

class SecondActivity : AppCompatActivity() {
    private lateinit var binding: SectionActivitySecondBinding
    private lateinit var viewModel: SecondActivityViewModel

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = DataBindingUtil.setContentView(this, R.layout.activity_second)
        viewModel = ViewModelProvider(this).get(SecondActivityViewModel::class.java)

        binding.apply {
            resultTextView.text = viewModel.getTotal().toString()
            insertButton.setOnClickListener() {
                viewModel.setTotal(inputEditText.text.toString().toInt())
                resultTextView.text = viewModel.getTotal().toString()
            }
        }
    }
}

 

SecondActivityViewModel

class SecondActivityViewModel:ViewModel() {
    private var total = 0

    fun getTotal(): Int {
        return total
    }

    fun setTotal(input: Int) {
        total+=input
    }
}

 

activity_second.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">

    <ScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent">

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

            <EditText
                android:id="@+id/input_edit_text"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginTop="171dp"
                android:ems="10"
                android:hint="0"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toTopOf="parent" />

            <Button
                android:id="@+id/insert_button"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginTop="100dp"
                android:hint="Add"
                android:text="Add"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toBottomOf="@+id/input_edit_text" />

            <TextView
                android:id="@+id/result_text_view"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginTop="85dp"
                android:hint="0"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toBottomOf="@+id/insert_button" />

        </androidx.constraintlayout.widget.ConstraintLayout>
    </ScrollView>
</layout>

 

activity_second 화면

 

 

설명

"SecondActivitiy"는 입력한 숫자를 더해 하단에 표시해줍니다.

MainActivity와 동일하게 ViewModel을 사용하여 Rotation 시에도 Configuration이 destroy 되지 않고 유지됩니다.

'Android' 카테고리의 다른 글

[Android] LiveData  (0) 2021.03.14
[Android] ViewModelFactory  (0) 2021.03.07
[Android] DataBinding  (0) 2021.03.02
[Android] MVVM 패턴  (0) 2020.08.11
[Android] LiveData 소개  (0) 2020.08.10
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2025/02   »
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
글 보관함