Fragments Flashcards
Fragments
What is Fragment Lifecycle ?
How to communicate with Fragments ?
To keep fragments self-contained, you should not have fragments communicate directly with other fragments or with its host activity. The Fragment library provides two options for communication:
- Shared ViewModel and
- Fragment Result API.
The recommended option depends on the use case. To share persistent data with any custom APIs, you should use a ViewModel. For a one-time result with data that can be placed in a Bundle, you should use the Fragment Result API.
How to use ViewModel to communicate between your fragments and activities ?
Share data using a ViewModel :
ViewModel is an ideal choice when you need to share data between multiple fragments or between fragments and their host activity. ViewModel objects store and manage UI data.
Share data with the host activity:
In some cases, you might need to share data between fragments and their host activity.
For example, you may want to toggle a global UI component based on an interaction within a fragment. Consider the following ItemViewModel:
class ItemViewModel : ViewModel() {
private val mutableSelectedItem = MutableLiveData()
val selectedItem: LiveData get() = mutableSelectedItem
fun selectItem(item: Item) { mutableSelectedItem.value = item }
}
In this example, the data being stored is wrapped in a MutableLiveData class. LiveData is a lifecycle-aware observable data holder class. MutableLiveData allows its value to be changed. Both your fragment and its host activity can retrieve a shared instance of a ViewModel with activity scope by passing the activity into the ViewModelProvider constructor. The ViewModelProvider handles instantiating the ViewModel or retrieving it if it already exists. Both components can observe and modify this data:
class MainActivity : AppCompatActivity() {
// Using the viewModels() Kotlin property delegate from the activity-ktx // artifact to retrieve the ViewModel in the activity scope
private val viewModel: ItemViewModel by viewModels()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
viewModel.selectedItem.observe(this, Observer { item ->
// Perform an action with the latest item data
}) }
}
class ListFragment : Fragment() {
// Using the activityViewModels() Kotlin property delegate from the
// fragment-ktx artifact to retrieve the ViewModel in the activity scope
private val viewModel: ItemViewModel by activityViewModels()
// Called when the item is clicked
fun onItemClicked(item: Item) {
// Set a new item
viewModel.selectItem(item)
}
}
How to share data between a parent and child fragment ?
Share data between a parent and child fragment:
When working with child fragments, your parent fragment and its child fragments might need to share data with each other. To share data between these fragments, use the parent fragment as the ViewModel scope.
class ListViewModel : ViewModel() {
val filters = MutableLiveData>()
private val originalList: LiveData>() = …
val filteredList: LiveData> = …
fun addFilter(filter: Filter) { … }
fun removeFilter(filter: Filter) { … }
}
class ListFragment : Fragment() {
// Using the activityViewModels() Kotlin property delegate from the
// fragment-ktx artifact to retrieve the ViewModel in the activity scope
private val viewModel: ListViewModel by activityViewModels()
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
viewModel.filteredList.observe(viewLifecycleOwner, Observer { list ->
// Update the list UI
}
}
}
class FilterFragment : Fragment() {
private val viewModel: ListViewModel by activityViewModels()
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
viewModel.filters.observe(viewLifecycleOwner, Observer { set ->
// Update the selected filters UI
}
}
fun onFilterSelected(filter: Filter) = viewModel.addFilter(filter)
fun onFilterDeselected(filter: Filter) = viewModel.removeFilter(filter)
}
How to scoping a ViewModel to the Navigation Graph ?
Scoping a ViewModel to the Navigation Graph :
If you’re using the Navigation library, you can also scope a ViewModel to the lifecycle of a destination’s NavBackStackEntry.
For example, the ViewModel could be scoped to the NavBackStackEntry for the ListFragment:
class ListFragment: Fragment() {
// Using the navGraphViewModels() Kotlin property delegate from the fragment-ktx
// artifact to retrieve the ViewModel using the NavBackStackEntry scope
// R.id.list_fragment == the destination id of the ListFragment destination
private val viewModel: ListViewModel by navGraphViewModels(R.id.list_fragment)
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { viewModel.filteredList.observe(viewLifecycleOwner, Observer {
item -> // Update the list UI
}
}
}
When replacing a fragment, how do you know the user can get back to the last fragment when they press the back button?
Understanding the life cycle of fragments is essential as a developer. You may need to explain that you know this as well as what the back stack is because this function may be necessary to use daily.
Example: “You should save each fragment transaction to the back stack to have the back button get the user to the last fragment. You can do this by calling ‘addToBackStack()’ before you commit that transaction.”
What lifecycle methods will trigger when FragmentB is added on top of FragmentA?
FragmentA is not affected when we inflate FragmentB with add
B-> onAttach
B-> onCreate
B-> onCreateView
B-> onActivityCreated
B-> onStart
B-> onResume
What lifecycle methods will trigger when FragmentB is pop-backed?
Since fragment B was added on top of A, fragment A is not affected by the removal of B.
B-> onPause
B-> onStop
B-> onDestroyView
B-> onDestroy
B-> onDetach
What lifecycle methods will trigger when FragmentB replaces FragmentA?
When Fragment B replaces Fragment A, Fragment A is destroyed and Fragment B is created. However, in case the transaction that had added Fragment A was saved using the addToBackStack method, then the backstack is holding a reference to that fragment from the previous transaction and hence only its view is destroyed. i.e. onDestroy and onDetach method of Fragment A will not be invoked.
B-> onAttach
B-> onCreate
A-> onPause
A-> onStop
A-> onDestroyView
A-> onDestroy
A-> onDetach
B-> onCreateView
B-> onActivityCreated
B-> onStart
B-> onResume
What happens if FrgametnB is pop-backed?
B -> onPause
B -> onStop
B -> onDestroy
B -> onDestroyView
B -> onDetach
A-> onAttach
A-> onCreate
A-> onCreateView
A-> onActivityCreated
A-> onStart
A-> onResume