สื่อสารกับส่วนย่อย

หากต้องการใช้ Fragment ซ้ำ ให้สร้างเป็นคอมโพเนนต์ที่สมบูรณ์ในตัว ที่กำหนดเลย์เอาต์และลักษณะการทำงานของตัวเอง เมื่อคุณให้คำจำกัดความ Fragment ที่นำกลับมาใช้ใหม่ได้ คุณสามารถเชื่อมโยง Fragment กับกิจกรรมและเชื่อมต่อ ด้วยตรรกะแอปพลิเคชันเพื่อให้รู้จัก UI แบบผสมโดยรวม

เพื่อตอบสนองต่อเหตุการณ์ของผู้ใช้อย่างเหมาะสมและการแชร์ข้อมูลสถานะ คุณมักจะ จึงจำเป็นต้องมีช่องทางการสื่อสารระหว่างกิจกรรมกับกิจกรรม หรือระหว่างส่วนย่อย 2 ส่วนขึ้นไป หากต้องการให้ส่วนย่อยอยู่ในตัวเอง ไม่มีส่วนย่อยที่สื่อสารกับส่วนย่อยโดยตรง หรือ กับกิจกรรมผู้จัด

ไลบรารี Fragment มีตัวเลือกการสื่อสาร 2 แบบ ได้แก่ ViewModel และส่วนย่อย API ของผลลัพธ์ ตัวเลือกที่แนะนำจะขึ้นอยู่กับกรณีการใช้งาน เพื่อแชร์ ข้อมูลถาวรที่มี API ที่กำหนดเอง ให้ใช้ ViewModel สำหรับ ผลลัพธ์แบบครั้งเดียวที่มีข้อมูลซึ่งสามารถวางไว้ใน Bundle ให้ใช้ Fragment API ของผลลัพธ์

ส่วนต่อไปนี้จะแสดงวิธีใช้ ViewModel และ Fragment ผลลัพธ์ API เพื่อสื่อสารระหว่างส่วนย่อยและกิจกรรม

แชร์ข้อมูลโดยใช้ ViewModel

ViewModel คือตัวเลือกที่เหมาะสมในกรณีต่อไปนี้ คุณต้องแชร์ข้อมูลระหว่าง ส่วนย่อยหลายรายการหรือระหว่างส่วนย่อยกับกิจกรรมโฮสต์ ViewModel ออบเจ็กต์จัดเก็บและ จัดการข้อมูล UI ดูข้อมูลเพิ่มเติมเกี่ยวกับ ViewModel ได้ที่ ดูภาพรวมของโมเดล

แชร์ข้อมูลกับกิจกรรมของโฮสต์

ในบางกรณี คุณอาจจำเป็นต้องแชร์ข้อมูลระหว่าง Fragment กับ กิจกรรมผู้จัด เช่น คุณอาจต้องการสลับ UI ส่วนกลาง คอมโพเนนต์ตามการโต้ตอบภายในส่วนย่อย

ลองพิจารณา ItemViewModel ต่อไปนี้

Kotlin

class ItemViewModel : ViewModel() {
    private val mutableSelectedItem = MutableLiveData<Item>()
    val selectedItem: LiveData<Item> get() = mutableSelectedItem

    fun selectItem(item: Item) {
        mutableSelectedItem.value = item
    }
}

Java

public class ItemViewModel extends ViewModel {
    private final MutableLiveData<Item> selectedItem = new MutableLiveData<Item>();
    public void selectItem(Item item) {
        selectedItem.setValue(item);
    }
    public LiveData<Item> getSelectedItem() {
        return selectedItem;
    }
}

ในตัวอย่างนี้ ข้อมูลที่จัดเก็บไว้จะรวมไว้ใน MutableLiveData LiveData เป็นแอปที่คำนึงถึงวงจร คลาสผู้ถือข้อมูลที่ได้รับอนุญาตให้สังเกตพฤติกรรมผู้ใช้ได้ MutableLiveData ให้ค่าของ มีการเปลี่ยนแปลง ดูข้อมูลเพิ่มเติมเกี่ยวกับ LiveData ได้ที่ ภาพรวม LiveData

ทั้งส่วนย่อยและกิจกรรมของโฮสต์สามารถเรียกข้อมูลอินสแตนซ์ที่แชร์ได้ ของ ViewModel ที่มีขอบเขตกิจกรรมโดยส่งกิจกรรมไปยัง ViewModelProvider เครื่องมือสร้างขึ้นมา ViewModelProvider จัดการการเริ่มต้น ViewModel หรือเรียกข้อมูล หากมีอยู่แล้ว ทั้ง 2 คอมโพเนนต์สามารถสังเกตและ แก้ไขข้อมูลนี้

Kotlin

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)
    }
}

Java

public class MainActivity extends AppCompatActivity {
    private ItemViewModel viewModel;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        viewModel = new ViewModelProvider(this).get(ItemViewModel.class);
        viewModel.getSelectedItem().observe(this, item -> {
            // Perform an action with the latest item data.
        });
    }
}

public class ListFragment extends Fragment {
    private ItemViewModel viewModel;

    @Override
    public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        viewModel = new ViewModelProvider(requireActivity()).get(ItemViewModel.class);
        ...
        items.setOnClickListener(item -> {
            // Set a new item.
            viewModel.select(item);
        });
    }
}

แชร์ข้อมูลระหว่างส่วนย่อย

ส่วนย่อยอย่างน้อย 2 ส่วนในกิจกรรมเดียวกันมักจะต้องสื่อสารกับ ระหว่างกัน ตัวอย่างเช่น สมมติว่ามีส่วนย่อยหนึ่งที่แสดงลิสต์รายการและ อีกแบบที่ช่วยให้ผู้ใช้ใช้ตัวกรองต่างๆ กับรายการได้ การนำกรณีนี้ไปใช้ก็ไม่ง่ายหากไม่มีส่วนใดๆ ติดต่อสื่อสารได้โดยตรง แต่หลังจากนั้นก็ไม่มี จบในตัว นอกจากนี้ Fragment ทั้ง 2 แบบต้องรองรับสถานการณ์ ที่ยังไม่มีการสร้างหรือมองเห็นได้อีกส่วนหนึ่ง

ส่วนย่อยเหล่านี้สามารถแชร์ ViewModel โดยใช้ขอบเขตกิจกรรม เพื่อจัดการการสื่อสารนี้ การแชร์ ViewModel ในลักษณะนี้ ส่วนย่อยไม่จำเป็นต้องรู้เกี่ยวกับกันและกัน และกิจกรรมนั้น คุณไม่จำเป็นต้องดำเนินการใดๆ เพื่ออำนวยความสะดวกในการสื่อสาร

ตัวอย่างต่อไปนี้แสดงการใช้ Fragment แบบ 2 ส่วนที่แชร์ ViewModel สำหรับการสื่อสาร:

Kotlin

class ListViewModel : ViewModel() {
    val filters = MutableLiveData<Set<Filter>>()

    private val originalList: LiveData<List<Item>>() = ...
    val filteredList: LiveData<List<Item>> = ...

    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)
}

Java

public class ListViewModel extends ViewModel {
    private final MutableLiveData<Set<Filter>> filters = new MutableLiveData<>();

    private final LiveData<List<Item>> originalList = ...;
    private final LiveData<List<Item>> filteredList = ...;

    public LiveData<List<Item>> getFilteredList() {
        return filteredList;
    }

    public LiveData<Set<Filter>> getFilters() {
        return filters;
    }

    public void addFilter(Filter filter) { ... }

    public void removeFilter(Filter filter) { ... }
}

public class ListFragment extends Fragment {
    private ListViewModel viewModel;

    @Override
    public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        viewModel = new ViewModelProvider(requireActivity()).get(ListViewModel.class);
        viewModel.getFilteredList().observe(getViewLifecycleOwner(), list -> {
            // Update the list UI.
        });
    }
}

public class FilterFragment extends Fragment {
    private ListViewModel viewModel;

    @Override
    public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
        viewModel = new ViewModelProvider(requireActivity()).get(ListViewModel.class);
        viewModel.getFilters().observe(getViewLifecycleOwner(), set -> {
            // Update the selected filters UI.
        });
    }

    public void onFilterSelected(Filter filter) {
        viewModel.addFilter(filter);
    }

    public void onFilterDeselected(Filter filter) {
        viewModel.removeFilter(filter);
    }
}

ส่วนย่อยทั้งสองใช้กิจกรรมโฮสต์เป็นขอบเขตสำหรับ ViewModelProvider เนื่องจากส่วนย่อยใช้ขอบเขตเดียวกัน จึงจะได้รับ อินสแตนซ์เดียวกันของ ViewModel ซึ่งช่วยให้สื่อสาร กลับไปกลับมา

แชร์ข้อมูลระหว่างส่วนย่อยระดับบนสุดและย่อย

เมื่อทำงานกับ Fragment ย่อย Fragment ระดับบนสุดและส่วนย่อย Fragment อาจต้องแชร์ข้อมูลให้แก่กัน เพื่อแชร์ข้อมูลระหว่าง ส่วนย่อยเหล่านี้ ให้ใช้ส่วนย่อยหลักเป็นขอบเขต ViewModel ดังที่แสดง ในตัวอย่างต่อไปนี้

Kotlin

class ListFragment: Fragment() {
    // Using the viewModels() Kotlin property delegate from the fragment-ktx
    // artifact to retrieve the ViewModel.
    private val viewModel: ListViewModel by viewModels()
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        viewModel.filteredList.observe(viewLifecycleOwner, Observer { list ->
            // Update the list UI.
        }
    }
}

class ChildFragment: Fragment() {
    // Using the viewModels() Kotlin property delegate from the fragment-ktx
    // artifact to retrieve the ViewModel using the parent fragment's scope
    private val viewModel: ListViewModel by viewModels({requireParentFragment()})
    ...
}

Java

public class ListFragment extends Fragment {
    private ListViewModel viewModel;

    @Override
    public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
        viewModel = new ViewModelProvider(this).get(ListViewModel.class);
        viewModel.getFilteredList().observe(getViewLifecycleOwner(), list -> {
            // Update the list UI.
        }
    }
}

public class ChildFragment extends Fragment {
    private ListViewModel viewModel;
    @Override
    public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
        viewModel = new ViewModelProvider(requireParentFragment()).get(ListViewModel.class);
        ...
    }
}

กำหนดขอบเขต ViewModel ไปยังกราฟการนำทาง

หากคุณกำลังใช้ไลบรารีการนำทาง คุณยังสามารถ กำหนดขอบเขต ViewModel ตามวงจรชีวิตของปลายทาง NavBackStackEntry สำหรับ เช่น ViewModel สามารถกำหนดขอบเขตเป็น NavBackStackEntry สำหรับ ListFragment:

Kotlin

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.
        }
    }
}

Java

public class ListFragment extends Fragment {
    private ListViewModel viewModel;

    @Override
    public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
    NavController navController = NavHostFragment.findNavController(this);
        NavBackStackEntry backStackEntry = navController.getBackStackEntry(R.id.list_fragment)

        viewModel = new ViewModelProvider(backStackEntry).get(ListViewModel.class);
        viewModel.getFilteredList().observe(getViewLifecycleOwner(), list -> {
            // Update the list UI.
        }
    }
}

สำหรับข้อมูลเพิ่มเติมเกี่ยวกับการกำหนดขอบเขต ViewModel เป็น NavBackStackEntry โปรดดู โต้ตอบกับคอมโพเนนต์การนำทางแบบเป็นโปรแกรม

รับผลลัพธ์โดยใช้ Fragment Result API

ในบางกรณี คุณอาจต้องการส่งค่าแบบครั้งเดียวระหว่าง 2 ส่วน หรือระหว่างส่วนย่อยกับกิจกรรมโฮสต์ ตัวอย่างเช่น คุณอาจมี ส่วนย่อยที่อ่านคิวอาร์โค้ดและส่งข้อมูลกลับไปยังส่วนย่อยก่อนหน้า

ใน Fragment เวอร์ชัน 1.3.0 ขึ้นไป แต่ละรายการ FragmentManager implements FragmentResultOwner ซึ่งหมายความว่า FragmentManager สามารถทำหน้าที่เป็นร้านค้ากลางสำหรับส่วนย่อย ผลลัพธ์ การเปลี่ยนแปลงนี้ช่วยให้คอมโพเนนต์สื่อสารถึงกันได้โดย ตั้งค่าผลลัพธ์ส่วนย่อยแล้วรอฟังผลลัพธ์เหล่านั้น โดยไม่จำเป็นต้อง องค์ประกอบเหล่านั้นให้อ้างอิงกันและกันได้โดยตรง

ส่งผลลัพธ์ระหว่างส่วนย่อย

หากต้องการส่งข้อมูลกลับไปยังส่วนย่อย A จากส่วนย่อย B ให้ตั้งค่า Listener ผลลัพธ์ก่อน บน Fragment A คือ Fragment ที่รับผลลัพธ์ โทร setFragmentResultListener() ใน FragmentManager ของส่วนย่อย A ดังที่แสดงในตัวอย่างต่อไปนี้

Kotlin

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    // Use the Kotlin extension in the fragment-ktx artifact.
    setFragmentResultListener("requestKey") { requestKey, bundle ->
        // We use a String here, but any type that can be put in a Bundle is supported.
        val result = bundle.getString("bundleKey")
        // Do something with the result.
    }
}

Java

@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    getParentFragmentManager().setFragmentResultListener("requestKey", this, new FragmentResultListener() {
        @Override
        public void onFragmentResult(@NonNull String requestKey, @NonNull Bundle bundle) {
            // We use a String here, but any type that can be put in a Bundle is supported.
            String result = bundle.getString("bundleKey");
            // Do something with the result.
        }
    });
}
วันที่ ส่วนย่อย b ส่งข้อมูลเพื่อแบ่งส่วน a โดยใช้ FragmentManager
รูปที่ 1 ส่วนย่อย B ส่งข้อมูลไปยังส่วนย่อย A โดยใช้ FragmentManager

ในส่วนย่อย B ส่วนที่สร้างผลลัพธ์ ให้กำหนดผลลัพธ์ ใน FragmentManager เดียวกันโดยใช้ requestKey เดียวกัน คุณทำได้ ดังนั้นด้วยการใช้ setFragmentResult() API:

Kotlin

button.setOnClickListener {
    val result = "result"
    // Use the Kotlin extension in the fragment-ktx artifact.
    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);
    }
});

Fragment A จะได้รับผลลัพธ์และเรียกใช้ Callback ของผู้ฟัง เมื่อส่วนย่อย STARTED

คุณมี Listener เพียงรายการเดียวและผลลัพธ์สำหรับคีย์หนึ่งๆ ได้ หากคุณโทรหา setFragmentResult() มากกว่า 1 ครั้งสำหรับคีย์เดียวกัน และหาก Listener ไม่ใช่ STARTED ระบบจะแทนที่ผลลัพธ์ที่รอดำเนินการด้วยผลลัพธ์ที่อัปเดต ผลลัพธ์

หากคุณตั้งค่าผลลัพธ์โดยไม่มี Listener ที่เกี่ยวข้องให้รับผลลัพธ์นั้น ระบบจะจัดเก็บผลลัพธ์ไว้ใน FragmentManager จนกว่าคุณจะตั้งค่า Listener ด้วย คีย์เดียวกัน เมื่อผู้ฟังได้รับผลลัพธ์และเริ่มการทำงานของ onFragmentResult() Callback ระบบล้างผลลัพธ์แล้ว ลักษณะการทำงานนี้มี ผลกระทบหลัก 2 ประการ ได้แก่

  • ส่วนย่อยในกองหลังจะไม่ได้รับผลลัพธ์จนกว่าจะ โดนระเบิดและเป็น STARTED
  • หากส่วนย่อยที่รอฟังผลลัพธ์คือ STARTED เมื่อตั้งค่าผลลัพธ์แล้ว Callback ของผู้ฟังจะเริ่มทำงานทันที

ผลการทดสอบส่วนย่อย

ใช้ FragmentScenario เพื่อทดสอบการโทรไปยัง setFragmentResult() และ setFragmentResultListener() สร้างสถานการณ์สำหรับส่วนย่อยภายใต้การทดสอบโดยใช้ launchFragmentInContainer หรือ launchFragment, จากนั้นจึงเรียกใช้เมธอดที่ยังไม่ได้ทดสอบด้วยตนเอง

หากต้องการทดสอบ setFragmentResultListener() ให้สร้างสถานการณ์ที่มี ส่วนย่อยที่เรียกไปยัง setFragmentResultListener() ถัดไป โทรหา setFragmentResult() โดยตรงและยืนยันผลลัพธ์:

@Test
fun testFragmentResultListener() {
    val scenario = launchFragmentInContainer<ResultListenerFragment>()
    scenario.onFragment { fragment ->
        val expectedResult = "result"
        fragment.parentFragmentManager.setFragmentResult("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)
        // Use the Kotlin extension in the fragment-ktx artifact.
        setFragmentResultListener("requestKey") { requestKey, bundle ->
            result = bundle.getString("bundleKey")
        }
    }
}

หากต้องการทดสอบ setFragmentResult() ให้สร้างสถานการณ์ที่มีส่วนย่อยที่ทำให้ โทรหา setFragmentResult() ถัดไป โทรหา setFragmentResultListener() โดยตรง และตรวจสอบผลลัพธ์ ดังนี้

@Test
fun testFragmentResult() {
    val scenario = launchFragmentInContainer<ResultFragment>()
    lateinit var actualResult: String?
    scenario.onFragment { fragment ->
        fragment.parentFragmentManager
                .setFragmentResultListener("requestKey") { requestKey, 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"
            // Use the Kotlin extension in the fragment-ktx artifact.
            setFragmentResult("requestKey", bundleOf("bundleKey" to result))
        }
    }
}

ส่งผลลัพธ์ระหว่างส่วนหลักและส่วนย่อย

หากต้องการส่งผลลัพธ์จากส่วนย่อยไปยังระดับบนสุด ใช้ getChildFragmentManager() จากส่วนย่อยระดับบนแทน getParentFragmentManager() เมื่อโทรหา setFragmentResultListener()

Kotlin

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    // Set the listener on the child fragmentManager.
    childFragmentManager.setFragmentResultListener("requestKey") { key, bundle ->
        val result = bundle.getString("bundleKey")
        // Do something with the result.
    }
}

Java

@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    // Set the listener on the child fragmentManager.
    getChildFragmentManager()
        .setFragmentResultListener("requestKey", this, new FragmentResultListener() {
            @Override
            public void onFragmentResult(@NonNull String requestKey, @NonNull Bundle bundle) {
                String result = bundle.getString("bundleKey");
                // Do something with the result.
            }
        });
}
วันที่ ส่วนย่อยย่อยสามารถใช้ FragmentManager เพื่อส่งผลลัพธ์
            ให้ผู้ปกครอง
รูปที่ 2 ส่วนย่อยที่ใช้ได้ FragmentManager เพื่อส่งผลลัพธ์ไปยังระดับบนสุด

ส่วนย่อยย่อยจะกำหนดผลลัพธ์ใน FragmentManager ผู้ปกครอง จากนั้นจะได้รับผลลัพธ์เมื่อส่วนย่อยเป็น STARTED:

Kotlin

button.setOnClickListener {
    val result = "result"
    // Use the Kotlin extension in the fragment-ktx artifact.
    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");
        // The child fragment needs to still set the result on its parent fragment manager.
        getParentFragmentManager().setFragmentResult("requestKey", result);
    }
});

รับผลลัพธ์ในกิจกรรมของผู้จัด

หากต้องการรับผลลัพธ์ส่วนย่อยในกิจกรรมโฮสต์ ให้ตั้งค่า Listener ผลลัพธ์ บนตัวจัดการส่วนย่อยโดยใช้ getSupportFragmentManager()

Kotlin

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        supportFragmentManager
                .setFragmentResultListener("requestKey", this) { requestKey, bundle ->
            // We use a String here, but any type that can be put in a Bundle is supported.
            val result = bundle.getString("bundleKey")
            // Do something with the result.
        }
    }
}

Java

class MainActivity extends AppCompatActivity {
    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        getSupportFragmentManager().setFragmentResultListener("requestKey", this, new FragmentResultListener() {
            @Override
            public void onFragmentResult(@NonNull String requestKey, @NonNull Bundle bundle) {
                // We use a String here, but any type that can be put in a Bundle is supported.
                String result = bundle.getString("bundleKey");
                // Do something with the result.
            }
        });
    }
}