Using fragmentFactory with Navigation Component
See original GitHub issueDescribe the bug
App crashes when I try to inject dependencies via the fragment constructor with Koin fragmentFactory
and JetPack navigation component.
To Reproduce
- Use JetPack navigation component to create a “single-activity” app.
- Create a fragment inside the navigation graph.
- Inject any dependency into the fragment’s constructor with Koin
fragmentFactory
. - 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:
- Created 4 years ago
- Comments:6 (2 by maintainers)
Top 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 >
Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free
Top Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
@abjorck Yes, the building process is successful by adding
fragment { NavHostFragment() }
to theappModule
. However, I am not sure how to get the instance of a specific navigation graph if an app contains multipleNavHostFragment
s.@nikhil-thakkar After adding
fragment { NavHostFragment() }
to theappModule
, the app works fine no matter the order ofsetupKoinFragmentFactory()
andsuper.onCreate(saveInstance)
on my testing devices.@seanwu1105 Could you try calling
setupKoinFragmentFactory()
beforesuper.onCreate(saveInstance)
? And the same holds true if you don’t useKoin
. You have to set theFragmentFactory
toSupportFragmentManager
before callingsuper.onCreate(saveInstance)
.