Fixed
Status Update
Comments
il...@google.com <il...@google.com> #2
Activity destinations should be considered exit points for your navigation graph - they are not part of the NavController's back stack and therefore not being sent to OnNavigatedListeners is working as intended.
il...@google.com <il...@google.com> #3
Thank you for your explanation, but although that is the intended behavior, it is still confusing.
In my opinion, the developer expects to be notified when any navigation action defined in the graph is performed, regardless the destination.
Although that action is considered an exit point, it is an action defined within the graph and it is indeed a navigation action happening in that graph, so I don't understand why it is not notified to the "OnNavigated" listener when it has indeed navigated, regardless if it affects or not the back stack.
I that is the intended behaviour, then it should be rather called something like "NavController.OnBackStackChangedListener".
In my opinion, the developer expects to be notified when any navigation action defined in the graph is performed, regardless the destination.
Although that action is considered an exit point, it is an action defined within the graph and it is indeed a navigation action happening in that graph, so I don't understand why it is not notified to the "OnNavigated" listener when it has indeed navigated, regardless if it affects or not the back stack.
I that is the intended behaviour, then it should be rather called something like "NavController.OnBackStackChangedListener".
Description
androidx.appcompat:appcompat:1.1.0
androidx.fragment:fragment:1.3.0-alpha03
Theme used: Theme.AppCompat.Light.DarkActionBar
Devices/Android versions reproduced on: Pixel 4 (RP1A.200115.001.C1)
Recreating this issue per comment on
Minimal code to reproduce is below. Clicking on the displayed button will cause a crash, as the prior expectation was that in onAttachFragment(), the FragmentManager will contain the Fragment that is passed as a parameter to onAttachFragment(), but this is no longer the case.
_______________
import android.graphics.Color
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.ViewGroup.LayoutParams
import android.widget.Button
import android.widget.ImageView
import androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.Fragment
private const val FRAGMENT_TAG = "tag"
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
if (savedInstanceState == null) {
supportFragmentManager
.beginTransaction()
.add(android.R.id.content, StartingFragment(), FRAGMENT_TAG)
.commit()
}
}
override fun onAttachFragment(fragment: Fragment) {
super.onAttachFragment(fragment)
val fragmentByTag = supportFragmentManager.findFragmentByTag(FRAGMENT_TAG)
if (fragment != fragmentByTag) {
throw IllegalStateException("Expected $fragment but found $fragmentByTag")
}
}
fun replaceFragment() {
supportFragmentManager
.beginTransaction()
.replace(android.R.id.content, ReplacementFragment(), FRAGMENT_TAG)
.addToBackStack(null)
.commit()
}
class StartingFragment : Fragment() {
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return Button(requireContext()).apply {
layoutParams = LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT)
text = "Replace fragment"
setOnClickListener {
(requireActivity() as MainActivity).replaceFragment()
}
}
}
}
class ReplacementFragment : Fragment() {
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return ImageView(requireContext()).apply {
layoutParams = LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)
setBackgroundColor(Color.BLUE)
}
}
}
}