This page contains miscellanies findings regarding android random topics. it is just for the ruff notes.
class ExampleFragment : Fragment(R.layout.example_fragment)
You can add your fragment to the activity's view hierarchy either by defining the fragment in your activity's layout file or by defining a fragment container in your activity's layout file and then programmatically adding the fragment from within your activity. In either case, you need to add a FragmentContainerView that defines the location where the fragment should be placed within the activity's view hierarchy. It is strongly recommended to always use a FragmentContainerView as the container for fragments, as FragmentContainerView includes fixes specific to fragments that other view groups such as FrameLayout do not provide.
To declaratively add a fragment to your activity layout's XML, use a FragmentContainerView element.
Here's an example activity layout containing a single FragmentContainerView:
<!-- res/layout/example_activity.xml -->
<androidx.fragment.app.FragmentContainerView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/fragment_container_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:name="com.example.ExampleFragment" />
Note: You can use the class attribute instead of android:name as an alternative way to specify which Fragment to instantiate.
To programmatically add a fragment to your activity's layout, the layout should include a FragmentContainerView to serve as a fragment container, as shown in the following example:
<!-- res/layout/example_activity.xml -->
<androidx.fragment.app.FragmentContainerView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/fragment_container_view"
android:layout_width="match_parent"
android:layout_height="match_parent" />
class ExampleActivity : AppCompatActivity(R.layout.example_activity) {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
if (savedInstanceState == null) {
supportFragmentManager.commit {
setReorderingAllowed(true)
add<ExampleFragment>(R.id.fragment_container_view)
}
}
}
}
The arguments Bundle can then be retrieved from within your fragment by calling requireArguments(), and the appropriate Bundle getter methods can be used to retrieve each argument.
class ExampleFragment : Fragment(R.layout.example_fragment) {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
val someInt = requireArguments().getInt("some_int")
...
}
}
FragmentManager is the class responsible for performing actions on your app's fragments, such as adding, removing, or replacing them and adding them to the back stack.
You might never interact with FragmentManager directly if you're using the Jetpack Navigation library, as it works with the FragmentManager on your behalf. However, any app using fragments is using FragmentManager at some level, so it's important to understand what it is and how it works.
supportFragmentManager.commit {
replace<ExampleFragment>(R.id.fragment_container)
setReorderingAllowed(true)
addToBackStack("name") // Name can be null
}
You can get a reference to the current fragment within a layout container by using findFragmentById(). Use findFragmentById() to look up a fragment either by the given ID when inflated from XML or by the container ID when added in a FragmentTransaction. Here's an example:
supportFragmentManager.commit {
replace<ExampleFragment>(R.id.fragment_container)
setReorderingAllowed(true)
addToBackStack(null)
}
...
val fragment: ExampleFragment =
supportFragmentManager.findFragmentById(R.id.fragment_container) as ExampleFragment
val fragmentManager = ...
val fragmentTransaction = fragmentManager.beginTransaction()
val fragmentManager = ...
// The fragment-ktx module provides a commit block that automatically
// calls beginTransaction and commit for you.
fragmentManager.commit {
// Add operations here
}
Fragment CREATED
When your fragment reaches the CREATED state, it has been added to a FragmentManager and the onAttach() method has already been called.
This transition invokes the onCreate() callback. The callback also receives a savedInstanceState Bundle argument containing any state previously saved by onSaveInstanceState(). Note that savedInstanceState has a null value the first time the fragment is created, but it is always non-null for subsequent recreations, even if you do not override onSaveInstanceState(). See Saving state with fragments for more details.
Caution: onSaveInstanceState(Bundle) is called only when the fragment's host activity calls its own onSaveInstanceState(Bundle).
override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
outState.putBoolean(IS_EDITING_KEY, isEditing)
outState.putString(RANDOM_GOOD_DEED_KEY, randomGoodDeed)
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
isEditing = savedInstanceState?.getBoolean(IS_EDITING_KEY, false)
randomGoodDeed = savedInstanceState?.getString(RANDOM_GOOD_DEED_KEY)
?: viewModel.generateRandomGoodDeed()
}
The Fragment library provides two options for communication: a shared ViewModel and the Fragment Result API. The recommended option depends on the use case. To share persistent data with custom APIs, use a ViewModel. For a one-time result with data that can be placed in a Bundle, use the Fragment Result API.
The following sections show you how to use ViewModel and the Fragment Result API to communicate between your fragments and activities.
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. For more information about ViewModel, see ViewModel overview.
Consider the following ItemViewModel:
class ItemViewModel : ViewModel() {
private val mutableSelectedItem = MutableLiveData<Item>()
val selectedItem: LiveData<Item> get() = mutableSelectedItem
fun selectItem(item: Item) {
mutableSelectedItem.value = item
}
}
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.
The following example shows how two fragments can use a shared ViewModel to communicate:
These fragments can share a ViewModel using their activity scope to handle this communication. By sharing the ViewModel in this way, the fragments don't need to know about each other, and the activity doesn't need to do anything to facilitate the communication.
Both fragments use their host activity as the scope for the ViewModelProvider. Because the fragments use the same scope, they receive the same instance of the ViewModel, which enables them to communicate back and forth.
use the parent fragment as the ViewModel scope, as shown in the following example:
private val viewModel: ListViewModel by viewModels({requireParentFragment()})
In some cases, you might want to pass a one-time value between two fragments or between a fragment and its host activity. For example, you might have a fragment that reads QR codes, passing the data back to a previous fragment.
FragmentManager can act as a central store for fragment results. This change lets components communicate with each other by setting fragment results and listening for those results, without requiring those components to have direct references to each other.
To pass data back to fragment A from fragment B, first set a result listener on fragment A, the fragment that receives the result. Call setFragmentResultListener() on fragment A's FragmentManager, as shown in the following example:
Same as previous example but just use the child fragment manager
To pass a result from a child fragment to a parent, use getChildFragmentManager() from the parent fragment instead of getParentFragmentManager() when calling setFragmentResultListener().
To receive a fragment result in the host activity, set a result listener on the fragment manager using getSupportFragmentManager().