Fragment 中的 Navigation.findNavController() 无法正常工作
Navigation.findNavController() in Fragment does not work properly
我正在尝试开发单一 activity 应用程序,该应用程序在特定条件下使用导航到我的主页片段中的相应片段(请参阅下面的代码片段)。但是当我以isLoggedIn == true
条件开始申请时,出现异常:
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)
这是我的代码片段:
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
}
}
问题是:如何在onCreateView()
return之前获取view
用于导航呢?
我尝试使用 解决方案,但我不明白我应该向 .findNavController(...)
传递什么参数。
P.S。 NavHostFragment 在 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>
根据 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)
}
}
findNavController(requireActivity())
.navigate(R.id.action_loginFragment_to_garageFragment)
使用此行代码,我认为对您有帮助
编辑: 如果您在片段中使用它,
Navigation.findNavController(getView()).navigate(R.id.action_loginFragment_to_garageFragment)
我正在尝试开发单一 activity 应用程序,该应用程序在特定条件下使用导航到我的主页片段中的相应片段(请参阅下面的代码片段)。但是当我以isLoggedIn == true
条件开始申请时,出现异常:
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)
这是我的代码片段:
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
}
}
问题是:如何在onCreateView()
return之前获取view
用于导航呢?
我尝试使用 .findNavController(...)
传递什么参数。
P.S。 NavHostFragment 在 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>
根据 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)
}
}
findNavController(requireActivity()) .navigate(R.id.action_loginFragment_to_garageFragment)
使用此行代码,我认为对您有帮助
编辑: 如果您在片段中使用它,
Navigation.findNavController(getView()).navigate(R.id.action_loginFragment_to_garageFragment)