liminal
liminal

Reputation: 1164

View.findNavController() vs Fragment.findNavController()

Anywhere in a NavHostFragment I can do findNavController().navigateUp()

Or, if in my Fragment I have a button to be used for navigation, I could do either:

editButton.setOnClickListener { v ->
    v.findNavController().navigateUp()
}

or

editButton.setOnClickListener {
    findNavController().navigateUp()
}

Why would I use one extension function vs the other when setting up a button click listener in a Fragment?

Upvotes: 22

Views: 32531

Answers (3)

mightyWOZ
mightyWOZ

Reputation: 8315

Although they are not identical as suggested by the top voted answer, the performance difference should be negligible in general scenarios. However if you use the v.findNavController() on a View which is deeply nested down, then you should prefer Fragment extension findNavController() as it will perform better.

In general I don't see any reason to prefer the v.findNavController over the Fragment extension. following is the complete code of this method from NavHostFragment and it only calls Navigation.findNavController if it doesn't find the NavController using the fragment

public static NavController findNavController(@NonNull Fragment fragment) {
    Fragment findFragment = fragment;
    while (findFragment != null) {
        if (findFragment instanceof NavHostFragment) {
            return ((NavHostFragment) findFragment).getNavController();
        }
        Fragment primaryNavFragment = findFragment.requireFragmentManager()
                 .getPrimaryNavigationFragment();
        if (primaryNavFragment instanceof NavHostFragment) {
            return ((NavHostFragment) primaryNavFragment).getNavController();
        }
        findFragment = findFragment.getParentFragment();
    }

    // Try looking for one associated with the view instead, if applicable
    View view = fragment.getView();
    if (view != null) {
        return Navigation.findNavController(view);
    }
    throw new IllegalStateException("Fragment " + fragment
                + " does not have a NavController set");
}

Upvotes: 2

CryptoCode
CryptoCode

Reputation: 1117

Thank you for the Java answer, I offer a ViewBinding solution in kotlin, doing the same

// NavHostFragment.kotlin
fun findMyNavController(@NonNull fragment: Fragment): NavController {
    return Navigation.findNavController(binding.root)
}

Upvotes: 4

jaychang0917
jaychang0917

Reputation: 1888

They are almost the same, Fragment.findNavController() is just a handy shortcut, it actually calls Navigation.findNavController(view) at the end. Both of them are getting the NavController from the root view of the fragment.

// NavHostFragment.java
public static NavController findNavController(@NonNull Fragment fragment) {
    ....
    View view = fragment.getView();
    if (view != null) {
        return Navigation.findNavController(view);
    }
    ...
}

Upvotes: 19

Related Questions