-
[안드로이드] ViewModel을 이용한 Fragment간 데이터 공유카테고리 없음 2024. 4. 29. 10:48
우선 Fragment를 변경할 수 있는 버튼과
Fragment를 교체할 수 있는 FrameLayout을 놔준다.
class MainActivity : AppCompatActivity() { private val binding by lazy { ActivityMainBinding.inflate(layoutInflater) } private val firstFragment by lazy { FirstFragment() } private val secondFragment by lazy { SecondFragment() } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(binding.root) switchFragment(firstFragment) } fun switchFirstFragment(view: View) { // 버튼 클릭 시 FirstFragment 표시 switchFragment(firstFragment) } fun switchSecondFragment(view: View) { // 버튼 클릭 시 SecondFragment 표시 switchFragment(secondFragment) } // Fragment를 교체하는 함수 private fun switchFragment(fragment: Fragment) { supportFragmentManager.beginTransaction().replace(binding.frameLayout.id, fragment).commit() } }
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent"> <FrameLayout android:id="@+id/frameLayout" android:layout_width="match_parent" android:layout_height="0dp" app:layout_constraintBottom_toTopOf="@id/linearLayout" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent"> </FrameLayout> <LinearLayout android:id="@+id/linearLayout" android:layout_width="match_parent" android:layout_height="0dp" android:orientation="horizontal" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent"> <Button android:id="@+id/firstFragmentButton" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1" android:onClick="switchFirstFragment" android:text="First" /> <Button android:id="@+id/secondFragmentButton" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1" android:onClick="switchSecondFragment" android:text="Second" /> </LinearLayout> </androidx.constraintlayout.widget.ConstraintLayout>
First/SecondFragment와 ViewModel를 만들어준다.
여기서 Fragment에 ViewModel을 선언할 때 viewModels()가 아닌 activityViewModels()를 사용한 이유는
ViewModel을 Activity에 종속시켜 같은 데이터를 공유하기 위함이다.
만약 viewModels()를 사용하게 된다면 각 Fragment에 종속되어 데이터가 공유되지 않는다.
class FirstFragment : Fragment() { private val viewModel: FragmentViewModel by activityViewModels() override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View { val binding = FragmentFirstBinding.inflate(inflater, container, false) binding.editText.addTextChangedListener { viewModel.setInput(it.toString()) } return binding.root } }
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent"> <EditText android:id="@+id/editText" android:layout_width="250dp" android:layout_height="wrap_content" android:hint="여기에 입력" android:textSize="30sp" app:layout_constraintBottom_toTopOf="@+id/textView" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintVertical_bias="0.95" /> <TextView android:id="@+id/textView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginBottom="428dp" android:gravity="center" android:text="First Fragment" android:textSize="40dp" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" /> </androidx.constraintlayout.widget.ConstraintLayout>
class SecondFragment : Fragment() { private val viewModel: FragmentViewModel by activityViewModels() override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View { val binding = FragmentSecondBinding.inflate(inflater, container, false) viewModel.input.observe(viewLifecycleOwner) { binding.inputText.text = it } return binding.root } }
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <TextView android:id="@+id/inputText" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="입력값" android:textSize="50sp" app:layout_constraintBottom_toTopOf="@+id/textView" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintVertical_bias="0.95" /> <TextView android:id="@+id/textView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginBottom="428dp" android:gravity="center" android:text="Second Fragment" android:textSize="40dp" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintHorizontal_bias="0.5" app:layout_constraintStart_toStartOf="parent" /> </androidx.constraintlayout.widget.ConstraintLayout>
class FragmentViewModel : ViewModel() { private val _input = MutableLiveData<String>() val input: LiveData<String> = _input fun setInput(input: String) { _input.value = input } }
작동 영상