On Android, transferring data between fragments can be done in different ways: transferring through the parent Activity using the ViewModel or even the Fragments API. The Fragment Target API has recently received the Deprecated status and Google recommends using the Fragment result API instead .
What is Fragment result API? This is a new tool from Google that allows you to transfer data between fragments using a key. For this, the FragmentManager is used, which in turn implements the FragmentResultOwner interface. FragmentResultOwner acts as a central repository for the data we pass between fragments.
How it works?
As mentioned above, our FragmentManager implements the FragmentResultOwner interface, which it stores ConcurrentHashMap<String, Bundle>
. This HashMap stores our Bundles by string key. As soon as one of the fragments is signed (or already signed), then it receives the result for the same key.
What is important to know :
- -
setResultFragmentListener()
,setFragmentResult()
, - “Key + Result (Bundle)“ 1
-
STARTED
-
DESTROYED
ResultListener
?
:
FragmentManager.setFragmentResult(key: String, bundle: Bundle)
, Bundle. Bundle .
Kotlin
button.setOnClickListener {
val result = "result"
// Kotlin fragment-ktx
setFragmentResult("requestKey", bundleOf("bundleKey" to result))
}
Java
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Bundle result = new Bundle();
result.putString("bundleKey", "result");
getParentFragmentManager().setFragmentResult("requestKey", result);
}
});
FragmentManager FragmentResultListener . FragmentManager.setFragmentResult()
Kotlin
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// Kotlin
setFragmentResultListener("requestKey") { key, bundle ->
// , Bundle-
val result = bundle.getString("bundleKey")
}
}
Java
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getParentFragmentManager().setFragmentResultListener("key", this, new FragmentResultListener() {
@Override
public void onFragmentResult(@NonNull String key, @NonNull Bundle bundle) {
String result = bundle.getString("bundleKey");
}
});
}
2 : key: String bundle: Bundle.
— , . — Bundle, .
Parent Fragment Manger
FragmentManager- :
- FragmentManager ( Activity), FragmentManager, Activity
- , childFragmentManager ( )
, FragmentResultListener FragmentManager-.
/ FragmentResultListener, FragmentScenario API, .
, FragmentManager? , FragmentResultListener :
@Test
fun testFragmentResult() {
val scenario = launchFragmentInContainer<ResultFragment>()
lateinit var actualResult: String?
scenario.onFragment { fragment ->
fragment.parentFragmentManagager.setResultListener("requestKey") { key, bundle ->
actualResult = bundle.getString("bundleKey")
}
}
onView(withId(R.id.result_button)).perform(click())
assertThat(actualResult).isEqualTo("result")
}
class ResultFragment : Fragment(R.layout.fragment_result) {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
view.findViewById(R.id.result_button).setOnClickListener {
val result = "result"
setResult("requestKey", bundleOf("bundleKey" to result))
}
}
}
, FragmentManager. FragmentResultListener .
@Test
fun testFragmentResultListener() {
val scenario = launchFragmentInContainer<ResultListenerFragment>()
scenario.onFragment { fragment ->
val expectedResult = "result"
fragment.parentFragmentManagager.setResult("requestKey", bundleOf("bundleKey" to expectedResult))
assertThat(fragment.result).isEqualTo(expectedResult)
}
}
class ResultListenerFragment : Fragment() {
var result : String? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setResultListener("requestKey") { key, bundle ->
result = bundle.getString("bundleKey")
}
}
}
FragmentResultListener , Google. , , , . , , , , .
In order to be able to use the FragmentResultListener, we need to connect the version of fragments 1.3.0-alpha04 or newer in the dependencies :
- Java version: androidx.fragment: fragment: 1.3.0-alpha04
- Kotlin version: androidx.fragment: fragment-ktx: 1.3.0-alpha04
- Tests: androidx.fragment: fragment-testing: 1.3.0-alpha04