preface

Fragment 1.3.0- Alpha04 has been released with a number of changes, including new ways of passing data between fragments

1.3.0 – alpha04 updates

API changes

First, let’s look at API changes

  • startActivityForResult()/onActivityResult()requestPermissions()/onRequestPermissionsResult()deprecated
  • prepareCall()renameregisterForActivityResult()
  • target fragment APIBe abandoned

The Activity Result API is on top

Since the ActivityResult API is provided to replace the onActivityResult mechanism, So the fragments startActivityForResult ()/onActivityResult () and requestPermissions ()/onRequestPermissionsResult was mark deprecated () method

It’s time to drop onActivityResult!

The article is very detailed and will not be repeated here

PrepareCall rename

It is worth noting that the place is prepareCall () was named registerForActivityResult ()

Note: apis can be added, removed, or changed while the version is in Alpha state. The Alpha version is therefore not suitable for production use

From another blog post of mine

Target Fragment API deprecated

The Target Fragment API has long been deprecated

SetTargetFragment was abandoned

A Target fragment requires direct access to an instance of another fragment, which is dangerous because you don’t know what state the target fragment is in. And the Target fragment does not support Navigation

Deprecate the Target Fragment API

So what’s a cleaner way to pass data between fragments?

A new way to pass data between fragments

As mentioned earlier, you can use the Target Fragment API in the same FragmentManager to pass data between fragments, but this approach requires direct access to the target fragment instance, which is dangerous. Because the state of the target fragment is unknown

So an API is officially available that allows you to set results on a fragment and use that result for the appropriate life of the fragment.

This method of passing data applies to the fragment in DialogFragment and Navigation

This change also includes the -ktx extension to ensure that kotlin users can pass FragmentResultListener as a lambda

FragmentA source
FragmentB source
demo

Source code analysis

As usual, let’s follow the official Commit log to see how the official implementation of this feature works

First, we add an abstraction like FragmentResultOwner that handles fragment results with two methods inside

  • setResult
  • setResultListener

The former is used to send data and the latter to receive data

FragmentResultOwner

The implementation class is FragmentManager

FragmentManager implement FragmentResultOwner

Let’s look at a concrete implementation of the FragmentManager two methods


public final void setFragmentResultListener(@NonNull final String requestKey,

        @NonNull final LifecycleOwner lifecycleOwner,

        @Nullable final FragmentResultListener listener)
 
{

    // Remove the listener corresponding to the requestKey if the listener is empty

    if (listener == null) {

        mResultListeners.remove(requestKey);

        return;

    }



    // Return when the fragment is in the DESTROYED state to avoid exceptions

    final Lifecycle lifecycle = lifecycleOwner.getLifecycle();

    if (lifecycle.getCurrentState() == Lifecycle.State.DESTROYED) {

        return;

    }



    Observe the lifecycle, fragment started receives callbacks, and destroyed removes callbacks

    LifecycleEventObserver observer = new LifecycleEventObserver() {

        @Override

        public void onStateChanged(@NonNull LifecycleOwner source,

                @NonNull Lifecycle.Event event)
 
{

            if (event == Lifecycle.Event.ON_START) {

                // once we are started, check for any stored results

                Bundle storedResult = mResults.get(requestKey);

                if(storedResult ! =null) {

                    // if there is a result, fire the callback

                    listener.onFragmentResult(requestKey, storedResult);

                    // and clear the result

                    setFragmentResult(requestKey, null);

                }

            }

            if (event == Lifecycle.Event.ON_DESTROY) {

                lifecycle.removeObserver(this);

                mResultListeners.remove(requestKey);

            }

        }

    };

    lifecycle.addObserver(observer);

    mResultListeners.put(requestKey, new LifecycleAwareResultListener(lifecycle, listener));

}

Copy the code

The above is the source code of this part

One thing to note here is that the Fragment Result API is based on the same FragmentManager

conclusion

Officials have been working on making the Fragment API more usable

Ian Lake in Fragments could: Past, Present, and Future (Android Dev Summit ’19) addresses the issue of communication between fragments. In the Future, fragments will integrate the lifecycle of both the fragment itself and its internal view. Support for multiple return stacks for the same FragmentManager

When I see the Fragment Result API, I suddenly have an idea. Is it a method to reset the state after Navigation jump return if it is applied to Navigation?

Do you have any thoughts in the comments section

About me

I am a Fly_with24

  • The Denver nuggets

  • Jane’s book

  • Github