Проблема с пустым экраном при навигации вверх или назад с помощью рукоятки и компонента навигацииAndroid

Форум для тех, кто программирует под Android
Ответить
Anonymous
 Проблема с пустым экраном при навигации вверх или назад с помощью рукоятки и компонента навигации

Сообщение Anonymous »

Я новичок и работаю над проектом Android, используя Hilt для внедрения зависимостей и компонент навигации для навигации. У меня есть один MainActivity в качестве хоста и два фрагмента: HomeFragment и DetailFragment.
Поток навигации работает нормально, когда я перехожу от HomeFragment к DetailFragment. Однако когда я пытаюсь вернуться назад, экран гаснет, и ни один из фрагментов не отображается.
MainActivity
`@AndroidEntryPoint
class MainActivity : BaseActivity() {
@Inject
lateinit var featuresNavigation: FeaturesNavigation

private val viewModel: MainViewModel by viewModels()
override fun getVM(): MainViewModel = viewModel

private lateinit var startDestination: Pair
override val layoutId = R.layout.activity_main

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)

val navHostFragment =
supportFragmentManager.findFragmentById(R.id.nav_host) as NavHostFragment
featuresNavigation.bind(navHostFragment)

with(intent) {
initGraph(this)
data = null
replaceExtras(Bundle())
}
}

private fun initGraph(intent: Intent?) {
startDestination = createStartDestination(intent)

if (startDestination.first == R.id.homeFragment) {
Timber.e("MainAct test initGraph")
featuresNavigation.setGraph(
R.navigation.main_navigation,
startDestination.first,
startDestination.second
)
}
}

private fun createStartDestination(intent: Intent?): Pair {
val bundle = intent?.getBundleExtra(Constants.KeyParam.KEY_EXTRAS)

return when (intent?.action) {

else -> {
R.id.homeFragment to null
}
}
}
}`

ActivityMain.xml
`







`

HomeFragment
`@AndroidEntryPoint
class HomeFragment :
BaseFragment(R.layout.fragment_home) {

@Inject
lateinit var featuresNavigation: FeaturesNavigation

private val viewModel: HomeViewModel by viewModels()
override fun getVM() = viewModel

override fun initView(savedInstanceState: Bundle?) {
super.initView(savedInstanceState)
activity?.window?.setBackgroundDrawable(null)

featuresNavigation.openDetail()
}
}`

DetailFragment
`@AndroidEntryPoint
class DetailFragment :
BaseFragment(R.layout.fragment_detail) {

@Inject
lateinit var featuresNavigation: FeaturesNavigation

private val viewModel: DetailViewModel by viewModels()
override fun getVM() = viewModel

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)

// TODO: Use the ViewModel
}

override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View {
return inflater.inflate(R.layout.fragment_detail, container, false)
}

override fun onBackPressed() {
featuresNavigation.navigateUp()
}
}`


AppNavigatorImpl
`@ActivityScoped
class AppNavigatorImpl @Inject constructor() : BaseNavigatorImpl(), FeaturesNavigation {

override fun openDetail(bundle: Bundle?) {
openScreen(R.id.action_homeFragment_to_detailFragment, bundle, R.id.detailFragment)
}
}`

Навигация по функциям
interface FeaturesNavigation : BaseNavigator {
fun openDetail(bundle: Bundle? = null)
}

main_navigation.xml
`








`

NavHostFramgent
public open class NavHostFragment : Fragment(), NavHost {
private var navHostController: NavHostController? = null
private var isPrimaryBeforeOnCreate: Boolean? = null
private var viewParent: View? = null

// State that will be saved and restored
private var graphId = 0
private var defaultNavHost = false

final override val navController: NavController
get() {
checkNotNull(navHostController) { "NavController is not available before onCreate()" }
return navHostController as NavHostController
}

@CallSuper
public override fun onAttach(context: Context) {
super.onAttach(context)

if (defaultNavHost) {
parentFragmentManager.beginTransaction()
.setPrimaryNavigationFragment(this)
.commit()
}
}

@CallSuper
public override fun onCreate(savedInstanceState: Bundle?) {
var context = requireContext()
navHostController = NavHostController(context)
navHostController!!.setLifecycleOwner(this)
while (context is ContextWrapper) {
if (context is OnBackPressedDispatcherOwner) {
navHostController!!.setOnBackPressedDispatcher(
(context as OnBackPressedDispatcherOwner).onBackPressedDispatcher
)
// Otherwise, caller must register a dispatcher on the controller explicitly
// by overriding onCreateNavHostController()
break
}
context = context.baseContext
}

navHostController!!.enableOnBackPressed(
isPrimaryBeforeOnCreate != null && isPrimaryBeforeOnCreate as Boolean
)
isPrimaryBeforeOnCreate = null
navHostController!!.setViewModelStore(viewModelStore)
onCreateNavHostController(navHostController!!)
var navState: Bundle? = null
if (savedInstanceState != null) {
navState = savedInstanceState.getBundle(KEY_NAV_CONTROLLER_STATE)
if (savedInstanceState.getBoolean(KEY_DEFAULT_NAV_HOST, false)) {
defaultNavHost = true
parentFragmentManager.beginTransaction()
.setPrimaryNavigationFragment(this)
.commit()
}
graphId = savedInstanceState.getInt(KEY_GRAPH_ID)
}
if (navState != null) {
// Navigation controller state overrides arguments
navHostController!!.restoreState(navState)
}
if (graphId != 0) {
// Set from onInflate()
navHostController!!.setGraph(graphId)
} else {
// See if it was set by NavHostFragment.create()
val args = arguments
val graphId = args?.getInt(KEY_GRAPH_ID) ?: 0
val startDestinationArgs = args?.getBundle(KEY_START_DESTINATION_ARGS)
if (graphId != 0) {
navHostController!!.setGraph(graphId, startDestinationArgs)
}
}

super.onCreate(savedInstanceState)
}

@CallSuper
protected open fun onCreateNavHostController(navHostController: NavHostController) {
onCreateNavController(navHostController)
}

@CallSuper
protected open fun onCreateNavController(navController: NavController) {
navController.navigatorProvider +=
DialogFragmentNavigator(requireContext(), childFragmentManager)
navController.navigatorProvider.addNavigator(createFragmentNavigator())
}

@CallSuper
public override fun onPrimaryNavigationFragmentChanged(isPrimaryNavigationFragment: Boolean) {
if (navHostController != null) {
navHostController?.enableOnBackPressed(isPrimaryNavigationFragment)
} else {
isPrimaryBeforeOnCreate = isPrimaryNavigationFragment
}
}

protected open fun createFragmentNavigator(): Navigator {
return FragmentNavigator(requireContext(), childFragmentManager, containerId)
}

public override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
val containerView = FragmentContainerView(inflater.context)
// When added via XML, this has no effect (since this FragmentContainerView is given the ID
// automatically), but this ensures that the View exists as part of this Fragment's View
// hierarchy in cases where the NavHostFragment is added programmatically as is required
// for child fragment transactions
containerView.id = containerId
return containerView
}

private val containerId: Int
get() {
val id = id
return if (id != 0 && id != View.NO_ID) {
id
} else R.id.nav_host_fragment_container
// Fallback to using our own ID if this Fragment wasn't added via
// add(containerViewId, Fragment)
}

public override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
check(view is ViewGroup) { "created host view $view is not a ViewGroup" }
Navigation.setViewNavController(view, navHostController)

if (view.getParent() != null) {
viewParent = view.getParent() as View
if (viewParent!!.id == id) {
Navigation.setViewNavController(viewParent!!, navHostController)
}
}
}

@CallSuper
public override fun onInflate(
context: Context,
attrs: AttributeSet,
savedInstanceState: Bundle?
) {
super.onInflate(context, attrs, savedInstanceState)
context.obtainStyledAttributes(
attrs,
androidx.navigation.R.styleable.NavHost
).use { navHost ->
val graphId = navHost.getResourceId(
androidx.navigation.R.styleable.NavHost_navGraph, 0
)
if (graphId != 0) {
this.graphId = graphId
}
}
context.obtainStyledAttributes(attrs, R.styleable.NavHostFragment).use { array ->
val defaultHost = array.getBoolean(R.styleable.NavHostFragment_defaultNavHost, false)
if (defaultHost) {
defaultNavHost = true
}
}
}

@CallSuper
public override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
val navState = navHostController!!.saveState()
if (navState != null) {
outState.putBundle(KEY_NAV_CONTROLLER_STATE, navState)
}
if (defaultNavHost) {
outState.putBoolean(KEY_DEFAULT_NAV_HOST, true)
}
if (graphId != 0) {
outState.putInt(KEY_GRAPH_ID, graphId)
}
}

public override fun onDestroyView() {
super.onDestroyView()
viewParent?.let { view ->
if (Navigation.findNavController(view) === navHostController) {
Navigation.setViewNavController(view, null)
}
}
viewParent = null
}

public companion object {
/**
* @hide
*/
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
public const val KEY_GRAPH_ID: String = "android-support-nav:fragment:graphId"

/**
* @hide
*/
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
public const val KEY_START_DESTINATION_ARGS: String =
"android-support-nav:fragment:startDestinationArgs"
private const val KEY_NAV_CONTROLLER_STATE =
"android-support-nav:fragment:navControllerState"
private const val KEY_DEFAULT_NAV_HOST = "android-support-nav:fragment:defaultHost"

@JvmStatic
public fun findNavController(fragment: Fragment): NavController {
var findFragment: Fragment? = fragment
while (findFragment != null) {
if (findFragment is NavHostFragment) {
return findFragment.navHostController as NavController
}
val primaryNavFragment = findFragment.parentFragmentManager
.primaryNavigationFragment
if (primaryNavFragment is NavHostFragment) {
return primaryNavFragment.navHostController as NavController
}
findFragment = findFragment.parentFragment
}

// Try looking for one associated with the view instead, if applicable
val view = fragment.view
if (view != null) {
return Navigation.findNavController(view)
}

// For DialogFragments, look at the dialog's decor view
val dialogDecorView = (fragment as? DialogFragment)?.dialog?.window?.decorView
if (dialogDecorView != null) {
return Navigation.findNavController(dialogDecorView)
}
throw IllegalStateException("Fragment $fragment does not have a navigationComponent.NavController set")
}

@JvmOverloads
@JvmStatic
public fun create(
@NavigationRes graphResId: Int,
startDestinationArgs: Bundle? = null
): NavHostFragment {
var b: Bundle? = null
if (graphResId != 0) {
b = Bundle()
b.putInt(KEY_GRAPH_ID, graphResId)
}
if (startDestinationArgs != null) {
if (b == null) {
b = Bundle()
}
b.putBundle(KEY_START_DESTINATION_ARGS, startDestinationArgs)
}
val result = NavHostFragment()
if (b != null) {
result.arguments = b
}
return result
}
}
}


Подробнее здесь: https://stackoverflow.com/questions/793 ... -component
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «Android»