Android Jetpack

Android ViewModel - 4 (Activity Fragment ViewModel 공유)

----___<<<<< 2021. 12. 22. 23:04

아래 영상에서 강의로 보실 수 있습니다.

 

https://www.inflearn.com/course/친절한-jetpack-1?inst=3b988560 

 

[중급편] 친절한 JETPACK 개론 <상> (Android Kotlin) - 인프런 | 강의

코틀린으로 안드로이드 개발을 위한 젯팩(JETPACK) 개론입니다. 안드로이드 개발을 하면서 사용할 수 있는 다양한 테크닉을 연습할 수 있습니다., - 강의 소개 | 인프런...

www.inflearn.com

 

 Android에서 Activity와 Fragment의 ViewModel 공유 방법에 대해서 알아보겠습니다.

 

 우선은 아까 만들었던 Activity와 ViewModel을 그대로 만들어보겠습니다.

 

class MainActivity : AppCompatActivity() {
private val TAG = MainActivity::class.java.simpleName
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.countShowArea.text = viewModel.countValue.toString()
binding.plusBtn.setOnClickListener {
viewModel.countValue++
binding.countShowArea.text = viewModel.countValue.toString()
}
binding.minusBtn.setOnClickListener {
viewModel.countValue--
binding.countShowArea.text = viewModel.countValue.toString()
}
}
}
view raw MainActivity.kt hosted with ❤ by GitHub
<?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">
<TextView
android:id="@+id/countShowArea"
android:textSize="50sp"
android:text="0"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/plusBtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="plus"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent" />
<Button
android:id="@+id/minusBtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="minus"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
/>
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>

 

 

 여기에서 중앙에 Fragment를 추가해주고, Fragment와 Activity를 ViewModel을 이용해서 공유해주는 방법을 사용해보겠습니다.

 

 아래와 같이 Fragment가 들어갈 영역을 만들고, Fragment가 실행되는 버튼을 만들어 줬습니다.

 

class MainActivity : AppCompatActivity() {
private val TAG = MainActivity::class.java.simpleName
lateinit var binding : ActivityMainBinding
lateinit var viewModel : MainViewModel
val manager = supportFragmentManager
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = DataBindingUtil.setContentView(this, R.layout.activity_main)
viewModel = ViewModelProvider(this).get(MainViewModel::class.java)
binding.countShowArea.text = viewModel.countValue.toString()
binding.fragmentStartBtn.setOnClickListener {
val transaction1 = manager.beginTransaction()
val fragment1 = BlankFragment1()
transaction1.replace(R.id.fragment1Area, fragment1)
transaction1.addToBackStack(null)
transaction1.commit()
val transaction2 = manager.beginTransaction()
val fragment2 = BlankFragment1()
transaction2.replace(R.id.fragment2Area, fragment2)
transaction2.addToBackStack(null)
transaction2.commit()
}
binding.plusBtn.setOnClickListener {
viewModel.countValue++
binding.countShowArea.text = viewModel.countValue.toString()
}
binding.minusBtn.setOnClickListener {
viewModel.countValue--
binding.countShowArea.text = viewModel.countValue.toString()
}
}
}
view raw MainActivity.kt hosted with ❤ by GitHub
<?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">
<TextView
android:id="@+id/countShowArea"
android:layout_width="match_parent"
android:layout_height="100dp"
android:layout_marginTop="10dp"
android:textSize="50dp"
android:gravity="center"
android:text="0"
app:layout_constraintTop_toTopOf="parent" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="200dp"
app:layout_constraintBottom_toTopOf="@+id/fragmentStartBtn"
app:layout_constraintTop_toBottomOf="@+id/countShowArea"
android:orientation="vertical">
<FrameLayout
android:id="@+id/fragment1Area"
android:background="#FF98FB98"
android:layout_width="match_parent"
android:layout_height="100dp">
</FrameLayout>
<FrameLayout
android:id="@+id/fragment2Area"
android:background="#FF98FB"
android:layout_width="match_parent"
android:layout_height="100dp">
</FrameLayout>
</LinearLayout>
<Button
android:text="FragmentStartBtn"
android:id="@+id/fragmentStartBtn"
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_marginBottom="50dp"
app:layout_constraintBottom_toBottomOf="parent" />
<Button
android:id="@+id/plusBtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="plus"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent" />
<Button
android:id="@+id/minusBtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="minus"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
/>
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>

 

 자, 이 부분에서 MainViewModel에 있는 값을 BlankFragment1, BlankFragment2와 공유해주도록 해보겠습니다.

 

 일단 MainActivity에는 MainViewModel의 값을 PLUS MINUS 버튼을 통해 조작할 수 있으니, Fragment에서도 조작하도록 해보겠습니다.

 

 BlankFragment1과 

 BlankFragment2의

 

 레이아웃을 아래와 같이 작성했습니다.

 

<?xml version="1.0" encoding="utf-8"?>
<layout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".BlankFragment1">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="@+id/fragment2TextArea"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:textSize="30dp"
android:text="0" />
<Button
android:id="@+id/fragment2Btn1"
android:text="+"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<Button
android:id="@+id/fragment2Btn2"
android:text="-"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
</FrameLayout>
</layout>
<?xml version="1.0" encoding="utf-8"?>
<layout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".BlankFragment2">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="@+id/fragment2TextArea"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:textSize="30dp"
android:text="0" />
<Button
android:id="@+id/fragment2Btn1"
android:text="+"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<Button
android:id="@+id/fragment2Btn2"
android:text="-"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
</FrameLayout>
</layout>

 

 그리고  BlankFragment1과 BlankFragment2의 코드를 아래와 같이 작성했습니다.

 

class BlankFragment1 : Fragment() {
private val TAG = BlankFragment1::class.java.simpleName
lateinit var binding : FragmentBlank1Binding
lateinit var viewModel : MainViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?, ): View? {
binding = DataBindingUtil.inflate(inflater, R.layout.fragment_blank1, container, false)
viewModel = ViewModelProvider(requireActivity()).get(MainViewModel::class.java)
binding.fragment2TextArea.text = viewModel.countValue.toString()
binding.fragment2Btn1.setOnClickListener {
viewModel.countValue++
}
binding.fragment2Btn2.setOnClickListener {
viewModel.countValue--
}
return binding.root
}
}
class BlankFragment2 : Fragment() {
private val TAG = BlankFragment2::class.java.simpleName
lateinit var binding : FragmentBlank2Binding
lateinit var viewModel : MainViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?,
): View? {
binding = DataBindingUtil.inflate(inflater, R.layout.fragment_blank2, container, false)
viewModel = ViewModelProvider(requireActivity()).get(MainViewModel::class.java)
binding.fragment2TextArea.text = viewModel.countValue.toString()
binding.fragment2Btn1.setOnClickListener {
viewModel.countValue++
}
binding.fragment2Btn2.setOnClickListener {
viewModel.countValue--
}
return inflater.inflate(R.layout.fragment_blank2, container, false)
}
}

 

 이렇게 하면, Fragment와 Activity간에 ViewModel의 데이터 공유를 할 수 있는 것을 볼 수 있습니다.

 

 

아래 영상에서 강의로 보실 수 있습니다.

 

https://www.inflearn.com/course/친절한-jetpack-1?inst=3b988560 

 

[중급편] 친절한 JETPACK 개론 <상> (Android Kotlin) - 인프런 | 강의

코틀린으로 안드로이드 개발을 위한 젯팩(JETPACK) 개론입니다. 안드로이드 개발을 하면서 사용할 수 있는 다양한 테크닉을 연습할 수 있습니다., - 강의 소개 | 인프런...

www.inflearn.com

 

 

 -- 참조

 

https://developer.android.com/codelabs/basic-android-kotlin-training-shared-viewmodel#9