Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Fragment Not Associated With A Fragment Manager

Tags:

I am writing some instrumented tests for an app with one activity and multiple fragments using the Navigation Component.

The code for my splash screen is as below:

class SplashFragment : Fragment(), KodeinAware {      override val kodein by Admin.instance.kodein      private var realm: Realm? = null      override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {         return inflater.inflate(R.layout.splash, container, false)     }      override fun onViewCreated(view: View, savedInstanceState: Bundle?) {         super.onViewCreated(view, savedInstanceState)          (activity as? AppCompatActivity)?.supportActionBar?.hide()          realm = Realm.getInstance(RealmUtil.realmConfig)          val result = realm!!.where<User>().findFirst()         val user = if (result != null) realm!!.copyFromRealm(result) else null          Handler().postDelayed({             if (user == null)                 findNavController().navigate(R.id.action_splashFragment_to_loginFragment) //navigate to login screen if no user exists             else                 findNavController().navigate(R.id.action_splashFragment_to_businessListFragment) //navigate to business list if user already logged in         }, 2000)     }      override fun onDestroy() {         super.onDestroy()          realm?.close()     } } 

I am attempting to test a fragment that comes after the splash screen but I keep getting the following error:

java.lang.IllegalStateException: Fragment SplashFragment{a1ca381 (5f5b98ae-c130-4e9b-9b77-0495561ef4f5)} not associated with a fragment manager. at androidx.fragment.app.Fragment.requireFragmentManager(Fragment.java:891) at androidx.navigation.fragment.NavHostFragment.findNavController(NavHostFragment.java:106) at androidx.navigation.fragment.FragmentKt.findNavController(Fragment.kt:29) at com.chargebot.collect.admin.fragment.onboarding.SplashFragment$onViewCreated$1.run(SplashFragment.kt:44) at android.os.Handler.handleCallback(Handler.java:873) at android.os.Handler.dispatchMessage(Handler.java:99) at androidx.test.espresso.base.Interrogator.loopAndInterrogate(Interrogator.java:148) at androidx.test.espresso.base.UiControllerImpl.loopUntil(UiControllerImpl.java:519) at androidx.test.espresso.base.UiControllerImpl.loopUntil(UiControllerImpl.java:478) at androidx.test.espresso.base.UiControllerImpl.injectKeyEvent(UiControllerImpl.java:201) at androidx.test.espresso.base.UiControllerImpl.injectString(UiControllerImpl.java:357) at androidx.test.espresso.action.TypeTextAction.perform(TypeTextAction.java:108) at androidx.test.espresso.ViewInteraction$SingleExecutionViewAction.perform(ViewInteraction.java:360) at androidx.test.espresso.ViewInteraction.doPerform(ViewInteraction.java:251) at androidx.test.espresso.ViewInteraction.access$100(ViewInteraction.java:64) at androidx.test.espresso.ViewInteraction$1.call(ViewInteraction.java:157) at androidx.test.espresso.ViewInteraction$1.call(ViewInteraction.java:154) at java.util.concurrent.FutureTask.run(FutureTask.java:266) at android.os.Handler.handleCallback(Handler.java:873) at android.os.Handler.dispatchMessage(Handler.java:99) at android.os.Looper.loop(Looper.java:193) at android.app.ActivityThread.main(ActivityThread.java:6669) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858) 

My test class is as follows:

@RunWith(AndroidJUnit4::class) @MediumTest class SignInTest {      @get: Rule     val login = ActivityScenarioRule(Home::class.java)      @Test     fun loginWithoutEmail_ShouldDisplayError() {         val scenario = launchFragmentInContainer<LoginFragment>()          onView(withId(R.id.password)).perform(typeText("samplePassword"), closeSoftKeyboard())         onView(withId(R.id.login)).perform(click())          onView(withId(com.google.android.material.R.id.snackbar_text)).check(matches(withText(R.string.enter_email)))     }      @Test     fun loginWithoutPassword_ShouldDisplayError() {         val scenario = launchFragmentInContainer<LoginFragment>()          onView(withId(R.id.email)).perform(typeText("[email protected]"), closeSoftKeyboard())         onView(withId(R.id.login)).perform(click())          onView(withId(com.google.android.material.R.id.snackbar_text)).check(matches(withText(R.string.enter_password)))     } } 

None of my test functions will execute because of the aforementioned error. What's the cause of the exception since tests I run on the Splash screen run successfully?

My nav_graph is as below:

<?xml version="1.0" encoding="utf-8"?> <navigation 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"     android:id="@+id/nav_graph"     app:startDestination="@id/splashFragment">      <fragment         android:id="@+id/splashFragment"         android:name="com.chargebot.collect.admin.fragment.onboarding.SplashFragment"         android:label="SplashFragment"         tools:layout="@layout/splash">         <action             android:id="@+id/action_splashFragment_to_loginFragment"             app:destination="@id/loginFragment"             app:popUpTo="@+id/splashFragment"             app:popUpToInclusive="true" />         <action             android:id="@+id/action_splashFragment_to_businessListFragment"             app:destination="@id/businessListFragment"             app:popUpTo="@+id/splashFragment"             app:popUpToInclusive="true" />     </fragment>     <fragment         android:id="@+id/registrationFragment"         android:name="com.chargebot.collect.admin.fragment.onboarding.RegistrationFragment"         android:label="RegistrationFragment"         tools:layout="@layout/registration">         <action             android:id="@+id/action_registrationFragment_to_businessListFragment"             app:destination="@id/businessListFragment"             app:popUpTo="@+id/registrationFragment"             app:popUpToInclusive="true" />         <action             android:id="@+id/action_registrationFragment_to_loginFragment"             app:destination="@id/loginFragment"             app:popUpTo="@+id/registrationFragment"             app:popUpToInclusive="true" />     </fragment>     <fragment         android:id="@+id/loginFragment"         android:name="com.chargebot.collect.admin.fragment.onboarding.LoginFragment"         android:label="LoginFragment"         tools:layout="@layout/login">         <action             android:id="@+id/action_loginFragment_to_businessListFragment"             app:destination="@id/businessListFragment"             app:popUpTo="@+id/loginFragment"             app:popUpToInclusive="true" />         <action             android:id="@+id/action_loginFragment_to_registrationFragment"             app:destination="@id/registrationFragment"             app:popUpTo="@+id/loginFragment"             app:popUpToInclusive="true" />     </fragment>     <fragment         android:id="@+id/businessListFragment"         android:name="com.chargebot.collect.admin.fragment.business.BusinessListFragment"         android:label="BusinessListFragment"         tools:layout="@layout/businesses_list">         <action             android:id="@+id/action_businessListFragment_to_newBusinessFragment"             app:destination="@id/newBusinessFragment" />         <action             android:id="@+id/action_businessListFragment_to_branchesFragment"             app:destination="@id/branchesFragment" />     </fragment>     <fragment         android:id="@+id/newBusinessFragment"         android:name="com.chargebot.collect.admin.fragment.business.NewBusinessFragment"         android:label="NewBusinessFragment"         tools:layout="@layout/add_business_layout">         <action             android:id="@+id/action_newBusinessFragment_to_businessListFragment"             app:destination="@id/businessListFragment" />     </fragment>     <fragment         android:id="@+id/branchesFragment"         android:name="com.chargebot.collect.admin.fragment.branch.BranchesFragment"         android:label="BranchesFragment"         tools:layout="@layout/branches_layout">         <action             android:id="@+id/action_branchesFragment_to_transactionsFragment"             app:destination="@id/transactionsFragment" />         <action             android:id="@+id/action_branchesFragment_to_newBranchFragment"             app:destination="@id/newBranchFragment" />         <action             android:id="@+id/action_branchesFragment_to_collectorsFragment"             app:destination="@id/collectorsFragment" />     </fragment>     <fragment         android:id="@+id/transactionsFragment"         android:name="com.chargebot.collect.admin.fragment.transactions.TransactionsFragment"         android:label="TransactionsFragment"         tools:layout="@layout/transactions" />     <fragment         android:id="@+id/newBranchFragment"         android:name="com.chargebot.collect.admin.fragment.branch.NewBranchFragment"         android:label="NewBranchFragment"         tools:layout="@layout/add_branch_layout" />     <fragment         android:id="@+id/collectorsFragment"         android:name="com.chargebot.collect.admin.fragment.collector.CollectorsFragment"         android:label="CollectorsFragment"         tools:layout="@layout/client_list_layout">         <action             android:id="@+id/action_collectorsFragment_to_newCollectorFragment"             app:destination="@id/newCollectorFragment" />         <action             android:id="@+id/action_collectorsFragment_to_transactionsFragment"             app:destination="@id/transactionsFragment" />         <action             android:id="@+id/action_collectorsFragment_to_collectorTransactions"             app:destination="@id/collectorTransactions" />     </fragment>     <fragment         android:id="@+id/newCollectorFragment"         android:name="com.chargebot.collect.admin.fragment.collector.NewCollectorFragment"         android:label="NewCollectorFragment"         tools:layout="@layout/new_client_layout" />     <fragment         android:id="@+id/collectorTransactions"         android:name="com.chargebot.collect.admin.fragment.transactions.CollectorTransactionsFragment"         android:label="CollectorTransactions"         tools:layout="@layout/transaction_layout">         <action             android:id="@+id/action_collectorTransactions_to_collectorsFragment"             app:destination="@id/collectorsFragment"             app:popUpTo="@id/collectorsFragment" />     </fragment>  </navigation> 
like image 536
Alex Kombo Avatar asked Apr 11 '19 11:04

Alex Kombo


People also ask

What does a fragment manager do?

FragmentManager is the class responsible for performing actions on your app's fragments, such as adding, removing, or replacing them, and adding them to the back stack.

Is Fragment Manager deprecated?

This class was deprecated in API level 28. Use the Support Library androidx.

How do I use FragmentContainerView?

Another way to simply add a Fragment to FragmentContainerView is by using the attribute android:name=”fragment_class_name_path" in XML. Both the attributes android:name or class are similar things we just need to give the classpath as a value to inflate the fragment.


1 Answers

I found out that in my case the issue was related to threading. I solved it with:

 lifecycleScope.launchWhenResumed {       findNavController().navigate(R.id.action_splashFragment_to_loginFragment)  } 

Would be good to know if this help you?!

like image 88
Daniel Rindt Avatar answered Oct 16 '22 19:10

Daniel Rindt