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.

StackOverflowError on Android API 19 and lower

See original GitHub issue

I have an Android project that is using KoDeIn 5.0.0.

In the project, there are these files:

interface GemCache {
    ... 
}

class GemCacheImpl(context: Context, id: Int) : GemCache {
    ...
}
interface GemRepository {
    ...
}

class GemRepositoryImpl(private val cache: GemCache) : GemRepository {
    ...
}
class FindGemUseCase(
    private val repository: GemRepository,
    private val threadExecutor: Scheduler,
    private val postExecutionThread: Scheduler
) {
    ...
}
class GemViewModel(private val findGemUseCase: FindGemUseCase) : ViewModel() {
    ...
}
class ViewModelFactory(
    private val creators: Map<Class<out ViewModel>, ViewModel>
) : ViewModelProvider.Factory {
    ...
}

Basically, the dependency graph is quite clear

ViewModelFactory -> Map<Class<out ViewModel>, ViewModel> Map<Class<out ViewModel>, ViewModel> contains Pair(GemViewModel::class.java, GemViewModel) GemViewModel -> FindGemUseCase -> GemRepository -> gemCache -> Context

So I defined these modules

val cacheModule: Kodein.Module = Kodein.Module {
    bind<GemCache>() with provider {
        GemCacheImpl(instance(), instance(tag = "resourceId"))
    }
}

val dataModule: Kodein.Module = Kodein.Module {
    bind<GemRepository>() with provider {
        GemRepositoryImpl(instance())
    }
}

val domainModule: Kodein.Module = Kodein.Module {

    bind<Scheduler>(tag = "threadExecutor") with provider {
        Schedulers.io()
    }

    bind<FindGemUseCase>() with provider {
        FindGemUseCase(
            instance(),
            instance(tag = "threadExecutor"),
            instance(tag = "postThread")
        )
    }
}

val presentationModule: Kodein.Module = Kodein.Module {

    bind() from setBinding<ViewModelEntry>()

    bind<ViewModelEntry>().inSet() with provider {
        GemViewModel::class.java to GemViewModel(instance())
    }

    bind<Map<Class<out ViewModel>, ViewModel>>() with provider {
        instance<ViewModelEntries>().toMap()
    }

    bind<ViewModelProvider.Factory>() with singleton {
        ViewModelFactory(instance())
    }
}

val dependencyGraph: Kodein.Module = Kodein.Module {
    import(cacheModule)
    import(dataModule)
    import(domainModule)
    import(presentationModule)
}

And then, in my application class…

class MyApp : Application(), KodeinAware {
    override val kodein : Kodein = Kodein {
        import(dependencyGraph)

        bind<Context>() with provider {
            this@MyApp
        }

        bind<Scheduler>(tag = "postThread") with singleton {
            AndroidSchedulers.mainThread()
        }

        constant(tag = "resourceId") with R.array.cache
    }
}

And MainActivity class…

class MainActivity : AppCompatActivity(), KodeinAware {
    override val kodein: Kodein by closestKodein()
    private val viewModelFactory: ViewModelProvider.Factory by instance()
    private val viewModel: GemViewModel by lazy {
        ViewModelProviders.of(this, viewModelFactory).get(GemViewModel::class.java)
    }
    ...
}

And here comes the killer, when I run the app on an Android api 19 or lower, I got this error on logcat:

04-18 19:43:21.952 3706-3706/me.la.leo.kodeindemo E/AndroidRuntime: FATAL EXCEPTION: main
    java.lang.StackOverflowError
        at org.kodein.di.TypesKt.getJavaType(types.kt)
        at org.kodein.di.TypesKt.getJavaType(types.kt:140)
        at org.kodein.di.TypesKt.getJavaType(types.kt:140)
        at org.kodein.di.TypesKt.getJavaType(types.kt:140)
        at org.kodein.di.TypesKt.getJavaType(types.kt:140)
        at org.kodein.di.TypesKt.getJavaType(types.kt:140)
        at org.kodein.di.TypesKt.getJavaType(types.kt:140)
        at org.kodein.di.TypesKt.getJavaType(types.kt:140)
        at org.kodein.di.TypesKt.getJavaType(types.kt:140)
        at org.kodein.di.TypesKt.getJavaType(types.kt:140)
        at org.kodein.di.TypesKt.getJavaType(types.kt:140)
        at org.kodein.di.TypesKt.getJavaType(types.kt:140)
        at org.kodein.di.TypesKt.getJavaType(types.kt:140)
        at org.kodein.di.TypesKt.getJavaType(types.kt:140)
        at org.kodein.di.TypesKt.getJavaType(types.kt:140)
        at org.kodein.di.TypesKt.getJavaType(types.kt:140)
        at org.kodein.di.TypesKt.getJavaType(types.kt:140)
        at org.kodein.di.TypesKt.getJavaType(types.kt:140)
        at org.kodein.di.TypesKt.getJavaType(types.kt:140)
        ...

The weird thing is that this works well on api 21 and higher Also, when I replace kodein 5.0.0 with 4.1.0, everything works on api 19 and lower

You can find the sample code here

The master branch is kodein 4.1.0 implementation The kodein5 is kodein 5.0.0 implementation

Issue Analytics

  • State:closed
  • Created 5 years ago
  • Comments:7 (2 by maintainers)

github_iconTop GitHub Comments

3reactions
SalomonBryscommented, Jun 18, 2018

Fixed in 5.0.1 😃

2reactions
SalomonBryscommented, Jun 5, 2018

Android SDK 19 and lower have many quirks in their reflexivity implementation. I confess I haven’t tested on SDK 19.

I’ll correct this for Kodein 5.0.1. I’ll keep you posted 😉

Read more comments on GitHub >

github_iconTop Results From Across the Web

StackOverflowError on Android API 19 and lower · Issue #127
I have an Android project that is using KoDeIn 5.0.0. In the project, there are these files: interface GemCache { .
Read more >
How to fix Expected Android API level 21+ but was 19 in ...
In my application i want get data from server, for get connect to server i used Retrofit, OkHttp. But when running application, show...
Read more >
StackOverflowError
StackOverflowError ; StackOverflowError. Added in API level 1 ... public class StackOverflowError ... Constructs a StackOverflowError with no detail message.
Read more >
How to Fix java.lang.StackOverflowError in Java
The java.lang.StackOverflowError is a runtime error which points to serious problems that cannot be caught by an application. The java.lang.
Read more >
APIs Used in the Android Market and Asked About in ...
How does the market demand for the USE of an. API drive the market for knowledge about it? Here, we analyze data from...
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