Home > Back-end >  Navigation.findNavController() in Fragment does not work properly
Navigation.findNavController() in Fragment does not work properly

Time:05-02

I'm trying develope single-activity application using the navigation to corresponding fragment from my home fragment under certain conditions (see my code fragment below). But when I start application with the condition isLoggedIn == true, an exception appears:

2022-05-01 17:42:22.888 14974-14974/com.example.shercofaqapp E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.shercofaqapp, PID: 14974
java.lang.IllegalStateException: Fragment LoginFragment{d69320f} (2bebfc01-ce4e-435e-be4f-821b5d142eb8 id=0x7f0a0096) did not return a View from onCreateView() or this was called before onCreateView().
    at androidx.fragment.app.Fragment.requireView(Fragment.java:2008)
    at com.example.shercofaqapp.view.LoginFragment.onCreateView(LoginFragment.kt:47)
    at androidx.fragment.app.Fragment.performCreateView(Fragment.java:2995)
    at androidx.fragment.app.FragmentStateManager.createView(FragmentStateManager.java:523)
    at androidx.fragment.app.FragmentStateManager.moveToExpectedState(FragmentStateManager.java:261)
    at androidx.fragment.app.FragmentStore.moveToExpectedState(FragmentStore.java:113)
    at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1374)
    at androidx.fragment.app.FragmentManager.dispatchStateChange(FragmentManager.java:2841)
    at androidx.fragment.app.FragmentManager.dispatchViewCreated(FragmentManager.java:2777)
    at androidx.fragment.app.Fragment.performViewCreated(Fragment.java:3020)
    at androidx.fragment.app.FragmentStateManager.createView(FragmentStateManager.java:551)
    at androidx.fragment.app.FragmentStateManager.moveToExpectedState(FragmentStateManager.java:261)
    at androidx.fragment.app.FragmentStore.moveToExpectedState(FragmentStore.java:113)
    at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1374)
    at androidx.fragment.app.FragmentManager.dispatchStateChange(FragmentManager.java:2841)
    at androidx.fragment.app.FragmentManager.dispatchActivityCreated(FragmentManager.java:2784)
    at androidx.fragment.app.FragmentController.dispatchActivityCreated(FragmentController.java:262)
    at androidx.fragment.app.FragmentActivity.onStart(FragmentActivity.java:478)
    at androidx.appcompat.app.AppCompatActivity.onStart(AppCompatActivity.java:246)
    at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1425)
    at android.app.Activity.performStart(Activity.java:7825)
    at android.app.ActivityThread.handleStartActivity(ActivityThread.java:3294)
    at android.app.servertransaction.TransactionExecutor.performLifecycleSequence(TransactionExecutor.java:221)
    at android.app.servertransaction.TransactionExecutor.cycleToPath(TransactionExecutor.java:201)
    at android.app.servertransaction.TransactionExecutor.executeLifecycleState(TransactionExecutor.java:173)
    at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:97)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2016)
    at android.os.Handler.dispatchMessage(Handler.java:107)
    at android.os.Looper.loop(Looper.java:214)
    at android.app.ActivityThread.main(ActivityThread.java:7356)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)

This is a fragment of my code:

package com.example.shercofaqapp.view

import android.content.Context
import android.os.Bundle
import android.text.TextUtils
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Toast
import androidx.databinding.DataBindingUtil
import androidx.navigation.Navigation
import com.example.shercofaqapp.R
import com.example.shercofaqapp.databinding.FragmentLoginBinding
import com.google.firebase.auth.FirebaseAuth
import com.google.firebase.auth.FirebaseUser
import kotlin.properties.Delegates

class LoginFragment : Fragment() {

    lateinit var binding: FragmentLoginBinding
    private var isLoggedIn by Delegates.notNull<Boolean>()

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {

        val sharedPref = requireActivity()
            .getSharedPreferences("MyPreferences", Context.MODE_PRIVATE)
        val editor = sharedPref.edit()
        var isLoggingIn = false


        binding = DataBindingUtil.inflate(
            inflater, R.layout.fragment_login, container, false)

        binding.apply {
            //Log in / sign up logic
            isLoggedIn = sharedPref.getBoolean("isLoggedIn", false)
            if (isLoggedIn) {
                Navigation.findNavController(requireView())
                    .navigate(R.id.action_loginFragment_to_garageFragment)
            }
        }
        return binding.root
    }
}

The question is: how can I get view for Navigation before onCreateView() return it?

I tried to use this solution, but I don't understand what argument I should pass to .findNavController(...) in my case.

P.S. NavHostFragment is in MainActivity:

<?xml version="1.0" encoding="utf-8"?>
<layout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    tools:context=".MainActivity">

    <androidx.fragment.app.FragmentContainerView
        android:id="@ id/containerView"
        android:name="androidx.navigation.fragment.NavHostFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:defaultNavHost="true"
        app:navGraph="@navigation/nav_graph" />

</layout>

CodePudding user response:

As per the Navigate to a destination documentation, you should use the findNavController() Kotlin extension on Fragment, which is a convenience wrapper around calling NavHostFragment.findNavController(this):

binding.apply {
    //Log in / sign up logic
    isLoggedIn = sharedPref.getBoolean("isLoggedIn", false)
    if (isLoggedIn) {
        // Make sure to:
        // 1. Add a dependency on navigation-fragment-ktx in your build.gradle
        // 2. import androidx.navigation.fragment.findNavController
        findNavController()
            .navigate(R.id.action_loginFragment_to_garageFragment)
    }
}

CodePudding user response:

findNavController(requireActivity()) .navigate(R.id.action_loginFragment_to_garageFragment)

use this code of line, I think it is helpful for you

  • Related