Si hay dos o más fragmentos en una actividad, necesitan comunicarse y compartir los datos entre ellos. La forma tradicional de compartir los datos entre los dos fragmentos es implementar la devolución de llamada mediante una interfaz que es engorrosa y puede generar excepciones. Pero la forma moderna de hacerlo es usar ViewModel compartido. Entonces, en este artículo, se demostró cómo se puede usar el ViewModel compartido para comunicarse entre los fragmentos. Eche un vistazo a la siguiente imagen para obtener una descripción general de la discusión.
Nota: Esta discusión se implementa en el lenguaje de programación Kotlin .
requisitos previos
Pasos para implementar la comunicación entre fragmentos
Paso 1: crear un proyecto de actividad vacío
Cree un proyecto de Android Studio de actividad vacío y seleccione Kotlin como lenguaje de programación. Consulte Android | ¿Cómo crear/comenzar un nuevo proyecto en Android Studio? .
Paso 2: agregar las dependencias requeridas
Las dependencias incluyen ViewModel y LiveData. Entonces, en el archivo Gradle del nivel de la aplicación, agregue las siguientes dependencias y sincronice el proyecto.
// lifecycle_version y las versiones de arquitectura pueden variar
def lifecycle_version = “2.3.1”def arch_version = “2.1.0”
// Ver modelo
implementación “androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_version”
// Datos en tiempo real
implementación “androidx.lifecycle:lifecycle-livedata-ktx:$lifecycle_version”
// Solo ciclos de vida (sin ViewModel o LiveData)
implementación “androidx.lifecycle:lifecycle-runtime-ktx:$lifecycle_version”
// arquitectura Extensiones del ciclo de vida
implementación «androidx.lifecycle:lifecycle-extensions:$arch_version»
Paso 3: trabajar con el archivo activity_main.xml
El diseño principal de la aplicación contiene los dos FrameLayouts que contienen los dos fragmentos. Para implementar lo mismo, invoque el siguiente código dentro del archivo activity_main.xml .
XML
<?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" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity" tools:ignore="HardcodedText"> <TextView android:id="@+id/textView" style="@style/TextAppearance.MaterialComponents.Headline6" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="16dp" android:layout_marginTop="16dp" android:text="Fragment 1:" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> <FrameLayout android:id="@+id/fragment_1_holder" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginStart="16dp" android:layout_marginTop="8dp" android:layout_marginEnd="16dp" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintHorizontal_bias="0.0" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/textView" /> <View android:id="@+id/view" android:layout_width="match_parent" android:layout_height="1dp" android:layout_marginTop="16dp" android:background="@color/green_700" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/fragment_1_holder" /> <TextView android:id="@+id/textView2" style="@style/TextAppearance.MaterialComponents.Headline6" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="16dp" android:layout_marginTop="16dp" android:text="Fragment 2: " app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/view" /> <FrameLayout android:id="@+id/fragment_2_holder" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginStart="16dp" android:layout_marginTop="8dp" android:layout_marginEnd="16dp" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintHorizontal_bias="0.0" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/textView2" /> </androidx.constraintlayout.widget.ConstraintLayout>
Paso 4: Implementación de ViewModel compartido
En el archivo SharedViewModel.kt hay un MutableLiveData de CharSequence para configurar los datos para EditTexts . Dos funciones setData y getData para actualizar esos datos en vivo mutables tan pronto como cambien los datos dentro de EditTexts.
Para implementar lo mismo, invoque el siguiente código.
Kotlin
import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel class SharedViewModel : ViewModel() { // Mutable LiveData which observed by LiveData // and updated to EditTexts when it is changed. private val mutableLiveData: MutableLiveData<CharSequence> = MutableLiveData() // function to set the changed // data from the EditTexts fun setData(input: CharSequence) { mutableLiveData.value = input } // function to get the changed data from the EditTexts fun getData(): MutableLiveData<CharSequence> = mutableLiveData }
Paso 5: Creando 2 Fragmentos
- Cree dos Fragmentos con sus propios diseños nombrándolos Fragment1.kt y Fragment2.kt .
- Para cada uno de los diseños del fragmento, contiene un EditText para obtener los datos para enviar para el fragmento 2 y un botón, cuando se hace clic, comparte los datos con otro fragmento.
- Para implementar el diseño del Fragmento 1, invoque el siguiente código dentro del archivo fragment_1.xml
XML
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout 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" android:clipToPadding="false" android:padding="4dp" tools:context=".Fragment1" tools:ignore="HardcodedText"> <com.google.android.material.textfield.TextInputLayout android:id="@+id/edit_text_layout_1" android:layout_width="match_parent" android:layout_height="wrap_content"> <com.google.android.material.textfield.TextInputEditText android:id="@+id/edit_text_from_fragment_1" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="Enter the data" /> </com.google.android.material.textfield.TextInputLayout> <Button android:id="@+id/send_button_fragment_1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@id/edit_text_layout_1" android:layout_alignParentEnd="true" android:layout_marginTop="8dp" android:layout_marginEnd="16dp" android:text="Send Data to Fragment 2" /> </RelativeLayout>
Para implementar el diseño del Fragmento 2, invoque el siguiente código dentro del archivo fragment_2.xml .
XML
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout 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" android:clipToPadding="false" android:padding="4dp" tools:context=".Fragment2" tools:ignore="HardcodedText"> <com.google.android.material.textfield.TextInputLayout android:id="@+id/edit_text_layout_2" android:layout_width="match_parent" android:layout_height="wrap_content"> <com.google.android.material.textfield.TextInputEditText android:id="@+id/edit_text_from_fragment_2" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="Enter the data" /> </com.google.android.material.textfield.TextInputLayout> <Button android:id="@+id/send_button_fragment_2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@id/edit_text_layout_2" android:layout_alignParentEnd="true" android:layout_marginTop="8dp" android:layout_marginEnd="16dp" android:text="Send Data to Fragment 1" /> </RelativeLayout>
Paso 6: Creación de instancias del modelo de vista compartida dentro de los archivos Fragment.kt
- Es necesario crear la instancia de ViewModel del tipo ShareViewModel cuando se crea la Actividad.
- Entonces, uno debe anular el método onActivityCreated() dentro de cada uno de los Fragmentos.
- Esto es así porque cuando vemos el ciclo de vida de los fragmentos, las vistas se crean y actualizan después de que se llama a onCreateView() y se llama a la devolución de llamada onAcrivityCreated() después de que se ejecuta onCreateView(). Por lo tanto, LiveData puede realizar un seguimiento de los elementos de la interfaz de usuario para los cuales se han actualizado. Eche un vistazo al siguiente gráfico para ver el ciclo de vida de la actividad del fragmento.
Para implementar lo mismo en ambos fragmentos, invoque el siguiente código dentro de Fragment1.kt .
Kotlin
import android.os.Bundle import android.text.Editable import androidx.fragment.app.Fragment import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import android.widget.Button import android.widget.EditText import androidx.lifecycle.Observer import androidx.lifecycle.ViewModelProviders class Fragment1 : Fragment() { private var sharedViewModelInstance: SharedViewModel? = null private var editTextFromFragment1: EditText? = null override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View? { val view: View = inflater.inflate(R.layout.fragment_1, container, false) val sendDataButton: Button = view.findViewById(R.id.send_button_fragment_1) editTextFromFragment1 = view.findViewById(R.id.edit_text_from_fragment_1) // as soon as the button is clicked // send the data to ViewModel // and the Live data will take care of // updating the data inside another Fragment sendDataButton.setOnClickListener { sharedViewModelInstance?.setData(editTextFromFragment1!!.text) } return view } override fun onActivityCreated(savedInstanceState: Bundle?) { super.onActivityCreated(savedInstanceState) // create instances of the shared view model // when the activity is created sharedViewModelInstance = ViewModelProviders.of(activity!!).get(SharedViewModel::class.java) // observe the data inside the view model that // is mutable live of type CharSequence and // set the data for edit text sharedViewModelInstance!!.getData().observe(viewLifecycleOwner, Observer { editTextFromFragment1!!.text = it as Editable? }) } }
Y lo mismo ocurre con el archivo Fragment2.kt , invoque el siguiente código.
Kotlin
import android.os.Bundle import android.text.Editable import androidx.fragment.app.Fragment import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import android.widget.Button import android.widget.EditText import androidx.lifecycle.Observer import androidx.lifecycle.ViewModelProviders class Fragment2 : Fragment() { private var sharedViewModelInstance: SharedViewModel? = null private var editTextFromFragment2: EditText? = null override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View? { val view: View = inflater.inflate(R.layout.fragment_2, container, false) val sendDataButton: Button = view.findViewById(R.id.send_button_fragment_2) editTextFromFragment2 = view.findViewById(R.id.edit_text_from_fragment_2) // as soon as the button is clicked // send the data to ViewModel // and the Live data will take care of // updating the data inside another Fragment sendDataButton.setOnClickListener { sharedViewModelInstance?.setData(editTextFromFragment2!!.text) } return view } override fun onActivityCreated(savedInstanceState: Bundle?) { super.onActivityCreated(savedInstanceState) // create instances of the shared view model // when the activity is created sharedViewModelInstance = ViewModelProviders.of(activity!!).get(SharedViewModel::class.java) // observe the data inside the view model that is mutable // live of type CharSequence and set the data for edit text sharedViewModelInstance!!.getData().observe(viewLifecycleOwner, Observer { editTextFromFragment2!!.text = it as Editable? }) } }
Paso 7: rellene los titulares de fragmentos utilizando el archivo MainActivity.kt
Dentro del archivo MainActivity.kt , es necesario rellenar los titulares de fragmentos de activity_main.xml, con ambos fragmentos. Para implementar lo mismo, invoque el siguiente código dentro del archivo MainActivity.kt .
Kotlin
import android.os.Bundle import androidx.appcompat.app.AppCompatActivity import androidx.fragment.app.FragmentTransaction class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) val fragmentTransaction: FragmentTransaction = supportFragmentManager.beginTransaction() fragmentTransaction.apply { add(R.id.fragment_1_holder, Fragment1()) add(R.id.fragment_2_holder, Fragment2()) commit() } } }
Producción:
Publicación traducida automáticamente
Artículo escrito por adityamshidlyali y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA