question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Using fragmentFactory with Navigation Component

See original GitHub issue

Describe the bug App crashes when I try to inject dependencies via the fragment constructor with Koin fragmentFactory and JetPack navigation component.

To Reproduce

  1. Use JetPack navigation component to create a “single-activity” app.
  2. Create a fragment inside the navigation graph.
  3. Inject any dependency into the fragment’s constructor with Koin fragmentFactory.
  4. App crashes when the navigation component tries to inflate the fragment. The following is the error log.
2020-01-08 15:02:30.459 27978-27978/com.example.koinfragmentfactoryissue E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.example.koinfragmentfactoryissue, PID: 27978
    java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.koinfragmentfactoryissue/com.example.koinfragmentfactoryissue.BaseActivity}: android.view.InflateException: Binary XML file line #22: Binary XML file line #22: Error inflating class fragment
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2781)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2859)
        at android.app.ActivityThread.-wrap11(Unknown Source:0)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1592)
        at android.os.Handler.dispatchMessage(Handler.java:106)
        at android.os.Looper.loop(Looper.java:164)
        at android.app.ActivityThread.main(ActivityThread.java:6518)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)
     Caused by: android.view.InflateException: Binary XML file line #22: Binary XML file line #22: Error inflating class fragment
     Caused by: android.view.InflateException: Binary XML file line #22: Error inflating class fragment
     Caused by: org.koin.core.error.NoBeanDefFoundException: No definition found for class:'androidx.navigation.fragment.NavHostFragment'. Check your definitions!
        at org.koin.core.scope.Scope.throwDefinitionNotFound(Scope.kt:245)
        at org.koin.core.scope.Scope.resolveInstance(Scope.kt:219)
        at org.koin.core.scope.Scope.get(Scope.kt:176)
        at org.koin.core.Koin.get(Koin.kt:113)
        at org.koin.core.Koin.get$default(Koin.kt:112)
        at org.koin.androidx.fragment.android.KoinFragmentFactory.instantiate(KoinFragmentFactory.kt:16)
        at androidx.fragment.app.FragmentLayoutInflaterFactory.onCreateView(FragmentLayoutInflaterFactory.java:97)
        at androidx.fragment.app.FragmentController.onCreateView(FragmentController.java:135)
        at androidx.fragment.app.FragmentActivity.dispatchFragmentsOnCreateView(FragmentActivity.java:356)
        at androidx.fragment.app.FragmentActivity.onCreateView(FragmentActivity.java:335)
        at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:780)
        at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:730)
        at android.view.LayoutInflater.rInflate(LayoutInflater.java:863)
        at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:824)
        at android.view.LayoutInflater.inflate(LayoutInflater.java:515)
        at android.view.LayoutInflater.inflate(LayoutInflater.java:423)
        at android.view.LayoutInflater.inflate(LayoutInflater.java:374)
        at androidx.appcompat.app.AppCompatDelegateImpl.setContentView(AppCompatDelegateImpl.java:555)
        at androidx.appcompat.app.AppCompatActivity.setContentView(AppCompatActivity.java:161)
        at com.example.koinfragmentfactoryissue.BaseActivity.onCreate(BaseActivity.kt:16)
        at android.app.Activity.performCreate(Activity.java:7023)
        at android.app.Activity.performCreate(Activity.java:7014)
        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1215)
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2734)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2859)
        at android.app.ActivityThread.-wrap11(Unknown Source:0)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1592)
        at android.os.Handler.dispatchMessage(Handler.java:106)
        at android.os.Looper.loop(Looper.java:164)
        at android.app.ActivityThread.main(ActivityThread.java:6518)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)

The following are some example codes.

// BaseApplication.kt
class BaseApplication : Application() {
    val appModule = module {
        single { MyApi() }
        fragment { MainFragment(get()) }
    }
    override fun onCreate() {
        super.onCreate()
        startKoin {
            androidLogger()
            androidContext(this@BaseApplication)
            fragmentFactory()
            modules(appModule)
        }
    }
}
// BaseActivity.kt
class BaseActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setupKoinFragmentFactory()
        setContentView(R.layout.activity_base)
        setSupportActionBar(toolbar)
        val navController = findNavController(R.id.nav_host_fragment)
        val appBarConfiguration = AppBarConfiguration(navController.graph)
        toolbar.setupWithNavController(navController, appBarConfiguration)
    }
}
// MainFragment.kt
class MainFragment(private val myApi: MyApi) : Fragment() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        myApi.hello()
    }
    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        return inflater.inflate(R.layout.fragment_main, container, false)
    }
}
// MyApi.kt
private const val TAG = "MyApi"
class MyApi {
    fun hello() {
        Log.i(TAG, "hello")
    }
}

Expected behavior The fragment should be successfully inflated with MyApi injected.

Koin project used and used version (please complete the following information): org.koin:koin-android:2.1.0-alpha-10 org.koin:koin-androidx-fragment:2.1.0-alpha-10

Issue Analytics

  • State:closed
  • Created 4 years ago
  • Comments:6 (2 by maintainers)

github_iconTop GitHub Comments

1reaction
seanwu1105commented, Feb 2, 2020

@abjorck Yes, the building process is successful by adding fragment { NavHostFragment() } to the appModule. However, I am not sure how to get the instance of a specific navigation graph if an app contains multiple NavHostFragments.

@nikhil-thakkar After adding fragment { NavHostFragment() } to the appModule, the app works fine no matter the order of setupKoinFragmentFactory() and super.onCreate(saveInstance) on my testing devices.

0reactions
nikhil-thakkarcommented, Jan 26, 2020

@seanwu1105 Could you try calling setupKoinFragmentFactory() before super.onCreate(saveInstance)? And the same holds true if you don’t use Koin. You have to set the FragmentFactory to SupportFragmentManager before calling super.onCreate(saveInstance).

Read more comments on GitHub >

github_iconTop Results From Across the Web

AndroidX Navigation with Dagger 2 & FragmentFactory
How to use it with the Navigation component? Extend NavHostFragment. With AndroidX Navigation library we usually use a NavHostFragment in ...
Read more >
Use FragmentFactory to construct Fragments ... - Issue Tracker
Component used: AndroidX Fragment, Navigation ... When using FragmentFactory attached to a fragment manager, FragmentNavigator$Destination.
Read more >
FragmentNavigator - Android Developers
Navigator that navigates through fragment transactions . Every destination using this Navigator must set a valid Fragment class name with android:name or ...
Read more >
View does not have a NavController set when using Fragment ...
I'm refactoring my app to use Fragment Factory. Everything was working fine with navigation components before the refactoring but now the ...
Read more >
Android FragmentFactory: Why You Need It and How to Use It
Fragments in Android. A fragment (an instance of the Fragment class) represents a behavior or part of the user interface in an activity...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found