Giter VIP home page Giter VIP logo

kodein's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

kodein's Issues

com.github.salomonbrys.kodein.Kodein$OverridingException: Binding bind<FragmentManager>() with ? { ? } must override an existing binding.

Hi, I'm trying to use the KodeinSupportFragment and I get this error:

 FATAL EXCEPTION: main
  Process: com.here.jumper, PID: 4460
  java.lang.RuntimeException: Unable to resume activity {com.here.jumper/com.here.jumper.flow.main.MainActivity}: com.github.salomonbrys.kodein.Kodein$OverridingException: Binding bind<FragmentManager>() with ? { ? } must override an existing binding.
      at android.app.ActivityThread.performResumeActivity(ActivityThread.java:3791)
      at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:3832)
      at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2994)
      at android.app.ActivityThread.-wrap14(ActivityThread.java)
      at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1631)
      at android.os.Handler.dispatchMessage(Handler.java:102)
      at android.os.Looper.loop(Looper.java:154)
      at android.app.ActivityThread.main(ActivityThread.java:6682)
      at java.lang.reflect.Method.invoke(Native Method)
      at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1520)
      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1410)
   Caused by: com.github.salomonbrys.kodein.Kodein$OverridingException: Binding bind<FragmentManager>() with ? { ? } must override an existing binding.
      at com.github.salomonbrys.kodein.KodeinContainer$Builder._checkOverrides(KodeinContainer.kt:220)
      at com.github.salomonbrys.kodein.KodeinContainer$Builder.access$_checkOverrides(KodeinContainer.kt:137)
      at com.github.salomonbrys.kodein.KodeinContainer$Builder$BindBinder.with(KodeinContainer.kt:273)
      at com.github.salomonbrys.kodein.Kodein$Builder$TypeBinder.with(Kodein.kt:192)
      at com.github.salomonbrys.kodein.android.SupportFragmentInjector$initializeInjector$fragmentModule$1.invoke(KodeinAndroidComponents.kt:400)
      at com.github.salomonbrys.kodein.android.SupportFragmentInjector$initializeInjector$fragmentModule$1.invoke(KodeinAndroidComponents.kt:383)
      at com.github.salomonbrys.kodein.Kodein$Builder.<init>(Kodein.kt:176)
      at com.github.salomonbrys.kodein.Kodein$Builder.import(Kodein.kt:273)
      at com.github.salomonbrys.kodein.android.KodeinAndroidComponentsKt$_inject$kodein$1.invoke(KodeinAndroidComponents.kt:37)
      at com.github.salomonbrys.kodein.android.KodeinAndroidComponentsKt$_inject$kodein$1.invoke(KodeinAndroidComponents.kt)
      at com.github.salomonbrys.kodein.Kodein$Builder.<init>(Kodein.kt:176)
      at com.github.salomonbrys.kodein.internal.KodeinImpl.<init>(KodeinImpl.kt:48)
      at com.github.salomonbrys.kodein.Kodein$Companion.invoke(Kodein.kt:423)
      at com.github.salomonbrys.kodein.Kodein$Companion.invoke$default(Kodein.kt:423)
      at com.github.salomonbrys.kodein.android.KodeinAndroidComponentsKt._inject(KodeinAndroidComponents.kt:34)
      at com.github.salomonbrys.kodein.android.KodeinAndroidComponentsKt.access$_inject(KodeinAndroidComponents.kt:1)
      at com.github.salomonbrys.kodein.android.SupportFragmentInjector$DefaultImpls.initializeInjector(KodeinAndroidComponents.kt:408)
      at com.github.salomonbrys.kodein.android.KodeinSupportFragment.initializeInjector(KodeinAndroidComponents.kt:421)
      at com.github.salomonbrys.kodein.android.KodeinSupportFragment.onCreate(KodeinAndroidComponents.kt:425)
      at ******.onCreate(BaseFlowFragment.kt:20)

This is the BaseFlowFragment (extended by other fragments):

abstract class BaseFlowFragment<T : ViewModel>() : KodeinSupportFragment(), LifecycleRegistryOwner {

    internal var mLifecycleRegistry = LifecycleRegistry(this)

    override fun getLifecycle(): LifecycleRegistry {
        return mLifecycleRegistry
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        //..
    }
    //..
}

Any idea?

Container composition

Kodein should support container composition.

Case scenario:

class MyApp: android.app.Application() {
  val components = Kodein {
    bind<EventBus>() with singleton { EventBus() }
  }
}

class MyActicity {
  val components = Kodein {
    bind<MyActivity.Presenter>() with singleton { MyActivity.Presenter(instance()) } 
    depends(MyApp.components) // Likeish. I would use Mortar's getSystemService trick to get app.components.
  }
}

Injection via delegate

I think that a really nice thing that can be done in Kotlin when it comes to dependency injection is that dependencies can be injected with delegates. I made a small thing that works like this, and essentially, this is what it would look like

fun main(args: Array<String>) {
    Injekt.configure {
        bind<DataSource> to {
            // get a data source here.
        }
    }
}

// OtherFile.kt
class OtherFIle {
    val ds: DataSource by inject()

}

The syntax doesn't have to be exactly like that, but I feel like something similar to that, where you can get dependencies with a delegate instead of passing a singular kodein instance to every class would be nice.

Proguard com.github.salomonbrys.kodein.TypeTokenKt

Is it safe to --dontwarn com.github.salomonbrys.kodein.TypeTokenKt?

Warning: com.github.salomonbrys.kodein.TypeTokenKt: can't find referenced method 'java.lang.String getTypeName()' in library class java.lang.reflect.Type
Warning: there were 1 unresolved references to library class members.
         You probably need to update the library versions.
         (http://proguard.sourceforge.net/manual/troubleshooting.html#unresolvedlibraryclassmember)

Multiton support

In provided example RandomDice provider creates a new instance for every invocation, and DataSource is a singleton.

Kodein misses of "singletonProvider", a function to lazy create a parametrized singleton instance.

Further enhancement: should be nice to define soft/weak singleton to avoid memory leak, but however this isn't my use case.

Compilation error when adding Kodein dependency

My Android application compiles just fine without Kodein. Simply adding the kodein and kodein-android dependencies produces the following compilation error. Removing them gets rid of the error.

Error:(25, 53) org.jetbrains.kotlin.codegen.CompilationException: Back-end (JVM) Internal error: Couldn't inline method call 'arrayOf' into
override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_probe_setup)
        if (ContextCompat.checkSelfPermission(this, Manifest.permission_group.LOCATION)
                != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.ACCESS_FINE_LOCATION,
                    Manifest.permission.ACCESS_COARSE_LOCATION), LOCATION)
        }
        var probeSelectionFragment = supportFragmentManager.findFragmentById(R.id.contentFrame) as ProbeSelectionFragment?
        if (probeSelectionFragment == null) {
            probeSelectionFragment = ProbeSelectionFragment()
            val transaction = supportFragmentManager.beginTransaction()
            transaction.add(R.id.contentFrame, probeSelectionFragment)
            transaction.commit()
        }

        probeSelectionPresenter = ProbeSelectionPresenter(probeSelectionFragment,
                this)
    }
cause: Not generated
Cause: Couldn't find declaration file for kotlin/KotlinPackage
File being compiled and position: (25,53) in /home/autrilla/src/Farmnet-Android/app/src/main/java/com/favega/farmnet/probes/setup/ProbeSetupActivity.kt
PsiElement: arrayOf(Manifest.permission.ACCESS_FINE_LOCATION,
                    Manifest.permission.ACCESS_COARSE_LOCATION)
The root cause was thrown at: InlineCodegen.java:212
    at org.jetbrains.kotlin.codegen.inline.InlineCodegen.genCallInner(InlineCodegen.java:158)
    at org.jetbrains.kotlin.codegen.CallGenerator.genCall(CallGenerator.kt:105)
    at org.jetbrains.kotlin.codegen.ExpressionCodegen.invokeMethodWithArguments(ExpressionCodegen.java:2429)
    at org.jetbrains.kotlin.codegen.ExpressionCodegen.invokeMethodWithArguments(ExpressionCodegen.java:2387)
    at org.jetbrains.kotlin.codegen.Callable$invokeMethodWithArguments$1.invoke(Callable.kt:44)
    at org.jetbrains.kotlin.codegen.Callable$invokeMethodWithArguments$1.invoke(Callable.kt:23)
    at org.jetbrains.kotlin.codegen.OperationStackValue.putSelector(StackValue.kt:65)
    at org.jetbrains.kotlin.codegen.StackValue.put(StackValue.java:109)
    at org.jetbrains.kotlin.codegen.StackValue.put(StackValue.java:102)
    at org.jetbrains.kotlin.codegen.CallGenerator$DefaultCallGenerator.genValueAndPut(CallGenerator.kt:63)
    at org.jetbrains.kotlin.codegen.CallBasedArgumentGenerator.generateExpression(CallBasedArgumentGenerator.java:73)
    at org.jetbrains.kotlin.codegen.ArgumentGenerator.generate(ArgumentGenerator.kt:59)
    at org.jetbrains.kotlin.codegen.CallBasedArgumentGenerator.generate(CallBasedArgumentGenerator.java:60)
    at org.jetbrains.kotlin.codegen.ExpressionCodegen.invokeMethodWithArguments(ExpressionCodegen.java:2409)
    at org.jetbrains.kotlin.codegen.ExpressionCodegen.invokeMethodWithArguments(ExpressionCodegen.java:2387)
    at org.jetbrains.kotlin.codegen.Callable$invokeMethodWithArguments$1.invoke(Callable.kt:44)
    at org.jetbrains.kotlin.codegen.Callable$invokeMethodWithArguments$1.invoke(Callable.kt:23)
    at org.jetbrains.kotlin.codegen.OperationStackValue.putSelector(StackValue.kt:65)
    at org.jetbrains.kotlin.codegen.StackValueWithLeaveTask.putSelector(StackValue.kt:57)
    at org.jetbrains.kotlin.codegen.StackValue.put(StackValue.java:109)
    at org.jetbrains.kotlin.codegen.StackValue.put(StackValue.java:102)
    at org.jetbrains.kotlin.codegen.ExpressionCodegen.gen(ExpressionCodegen.java:323)
    at org.jetbrains.kotlin.codegen.ExpressionCodegen$3.invoke(ExpressionCodegen.java:1217)
    at org.jetbrains.kotlin.codegen.ExpressionCodegen$3.invoke(ExpressionCodegen.java:1210)
    at org.jetbrains.kotlin.codegen.OperationStackValue.putSelector(StackValue.kt:65)
    at org.jetbrains.kotlin.codegen.StackValue.put(StackValue.java:109)
    at org.jetbrains.kotlin.codegen.StackValue.put(StackValue.java:102)
    at org.jetbrains.kotlin.codegen.ExpressionCodegen.generateBlock(ExpressionCodegen.java:1552)
    at org.jetbrains.kotlin.codegen.ExpressionCodegen.generateBlock(ExpressionCodegen.java:1499)
    at org.jetbrains.kotlin.codegen.CodegenStatementVisitor.visitBlockExpression(CodegenStatementVisitor.java:56)
    at org.jetbrains.kotlin.codegen.CodegenStatementVisitor.visitBlockExpression(CodegenStatementVisitor.java:22)
    at org.jetbrains.kotlin.psi.KtBlockExpression.accept(KtBlockExpression.java:44)
    at org.jetbrains.kotlin.codegen.ExpressionCodegen.genQualified(ExpressionCodegen.java:282)
    at org.jetbrains.kotlin.codegen.ExpressionCodegen.genStatement(ExpressionCodegen.java:341)
    at org.jetbrains.kotlin.codegen.ExpressionCodegen.gen(ExpressionCodegen.java:311)
    at org.jetbrains.kotlin.codegen.ExpressionCodegen.returnExpression(ExpressionCodegen.java:1887)
    at org.jetbrains.kotlin.codegen.FunctionGenerationStrategy$FunctionDefault.doGenerateBody(FunctionGenerationStrategy.java:50)
    at org.jetbrains.kotlin.codegen.FunctionGenerationStrategy$CodegenBased.generateBody(FunctionGenerationStrategy.java:72)
    at org.jetbrains.kotlin.codegen.FunctionCodegen.generateMethodBody(FunctionCodegen.java:365)
    at org.jetbrains.kotlin.codegen.FunctionCodegen.generateMethod(FunctionCodegen.java:204)
    at org.jetbrains.kotlin.codegen.FunctionCodegen.generateMethod(FunctionCodegen.java:139)
    at org.jetbrains.kotlin.codegen.FunctionCodegen.gen(FunctionCodegen.java:114)
    at org.jetbrains.kotlin.codegen.MemberCodegen.genFunctionOrProperty(MemberCodegen.java:180)
    at org.jetbrains.kotlin.codegen.ClassBodyCodegen.generateDeclaration(ClassBodyCodegen.java:124)
    at org.jetbrains.kotlin.codegen.ClassBodyCodegen.generateBody(ClassBodyCodegen.java:74)
    at org.jetbrains.kotlin.codegen.MemberCodegen.generate(MemberCodegen.java:117)
    at org.jetbrains.kotlin.codegen.MemberCodegen.genClassOrObject(MemberCodegen.java:231)
    at org.jetbrains.kotlin.codegen.PackageCodegen.generateClassOrObject(PackageCodegen.java:147)
    at org.jetbrains.kotlin.codegen.PackageCodegen.generateFile(PackageCodegen.java:98)
    at org.jetbrains.kotlin.codegen.PackageCodegen.generate(PackageCodegen.java:61)
    at org.jetbrains.kotlin.codegen.KotlinCodegenFacade.generatePackage(KotlinCodegenFacade.java:99)
    at org.jetbrains.kotlin.codegen.KotlinCodegenFacade.doGenerateFiles(KotlinCodegenFacade.java:77)
    at org.jetbrains.kotlin.codegen.KotlinCodegenFacade.compileCorrectFiles(KotlinCodegenFacade.java:44)
    at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.generate(KotlinToJVMBytecodeCompiler.kt:376)
    at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.analyzeAndGenerate(KotlinToJVMBytecodeCompiler.kt:275)
    at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.compileBunchOfSources(KotlinToJVMBytecodeCompiler.kt:194)
    at org.jetbrains.kotlin.cli.jvm.K2JVMCompiler.doExecute(K2JVMCompiler.kt:196)
    at org.jetbrains.kotlin.cli.jvm.K2JVMCompiler.doExecute(K2JVMCompiler.kt:49)
    at org.jetbrains.kotlin.cli.common.CLICompiler.exec(CLICompiler.java:181)
    at org.jetbrains.kotlin.gradle.tasks.AbstractKotlinCompile.callCompiler(Tasks.kt:87)
    at org.jetbrains.kotlin.gradle.tasks.AbstractKotlinCompile.compile(Tasks.kt:63)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.gradle.internal.reflect.JavaMethod.invoke(JavaMethod.java:75)
    at org.gradle.api.internal.project.taskfactory.AnnotationProcessingTaskFactory$StandardTaskAction.doExecute(AnnotationProcessingTaskFactory.java:227)
    at org.gradle.api.internal.project.taskfactory.AnnotationProcessingTaskFactory$StandardTaskAction.execute(AnnotationProcessingTaskFactory.java:220)
    at org.gradle.api.internal.project.taskfactory.AnnotationProcessingTaskFactory$StandardTaskAction.execute(AnnotationProcessingTaskFactory.java:209)
    at org.gradle.api.internal.AbstractTask$TaskActionWrapper.execute(AbstractTask.java:585)
    at org.gradle.api.internal.AbstractTask$TaskActionWrapper.execute(AbstractTask.java:568)
    at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeAction(ExecuteActionsTaskExecuter.java:80)
    at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeActions(ExecuteActionsTaskExecuter.java:61)
    at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.execute(ExecuteActionsTaskExecuter.java:46)
    at org.gradle.api.internal.tasks.execution.PostExecutionAnalysisTaskExecuter.execute(PostExecutionAnalysisTaskExecuter.java:35)
    at org.gradle.api.internal.tasks.execution.SkipUpToDateTaskExecuter.execute(SkipUpToDateTaskExecuter.java:64)
    at org.gradle.api.internal.tasks.execution.ValidatingTaskExecuter.execute(ValidatingTaskExecuter.java:58)
    at org.gradle.api.internal.tasks.execution.SkipEmptySourceFilesTaskExecuter.execute(SkipEmptySourceFilesTaskExecuter.java:52)
    at org.gradle.api.internal.tasks.execution.SkipTaskWithNoActionsExecuter.execute(SkipTaskWithNoActionsExecuter.java:52)
    at org.gradle.api.internal.tasks.execution.SkipOnlyIfTaskExecuter.execute(SkipOnlyIfTaskExecuter.java:53)
    at org.gradle.api.internal.tasks.execution.ExecuteAtMostOnceTaskExecuter.execute(ExecuteAtMostOnceTaskExecuter.java:43)
    at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter$EventFiringTaskWorker.execute(DefaultTaskGraphExecuter.java:203)
    at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter$EventFiringTaskWorker.execute(DefaultTaskGraphExecuter.java:185)
    at org.gradle.execution.taskgraph.AbstractTaskPlanExecutor$TaskExecutorWorker.processTask(AbstractTaskPlanExecutor.java:66)
    at org.gradle.execution.taskgraph.AbstractTaskPlanExecutor$TaskExecutorWorker.run(AbstractTaskPlanExecutor.java:50)
    at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor.process(DefaultTaskPlanExecutor.java:25)
    at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter.execute(DefaultTaskGraphExecuter.java:110)
    at org.gradle.execution.SelectedTaskExecutionAction.execute(SelectedTaskExecutionAction.java:37)
    at org.gradle.execution.DefaultBuildExecuter.execute(DefaultBuildExecuter.java:37)
    at org.gradle.execution.DefaultBuildExecuter.access$000(DefaultBuildExecuter.java:23)
    at org.gradle.execution.DefaultBuildExecuter$1.proceed(DefaultBuildExecuter.java:43)
    at org.gradle.execution.DryRunBuildExecutionAction.execute(DryRunBuildExecutionAction.java:32)
    at org.gradle.execution.DefaultBuildExecuter.execute(DefaultBuildExecuter.java:37)
    at org.gradle.execution.DefaultBuildExecuter.execute(DefaultBuildExecuter.java:30)
    at org.gradle.initialization.DefaultGradleLauncher$4.run(DefaultGradleLauncher.java:154)
    at org.gradle.internal.Factories$1.create(Factories.java:22)
    at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:90)
    at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:52)
    at org.gradle.initialization.DefaultGradleLauncher.doBuildStages(DefaultGradleLauncher.java:151)
    at org.gradle.initialization.DefaultGradleLauncher.access$200(DefaultGradleLauncher.java:32)
    at org.gradle.initialization.DefaultGradleLauncher$1.create(DefaultGradleLauncher.java:99)
    at org.gradle.initialization.DefaultGradleLauncher$1.create(DefaultGradleLauncher.java:93)
    at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:90)
    at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:62)
    at org.gradle.initialization.DefaultGradleLauncher.doBuild(DefaultGradleLauncher.java:93)
    at org.gradle.initialization.DefaultGradleLauncher.run(DefaultGradleLauncher.java:82)
    at org.gradle.launcher.exec.InProcessBuildActionExecuter$DefaultBuildController.run(InProcessBuildActionExecuter.java:94)
    at org.gradle.tooling.internal.provider.runner.BuildModelActionRunner.run(BuildModelActionRunner.java:46)
    at org.gradle.launcher.exec.ChainingBuildActionRunner.run(ChainingBuildActionRunner.java:35)
    at org.gradle.tooling.internal.provider.runner.SubscribableBuildActionRunner.run(SubscribableBuildActionRunner.java:58)
    at org.gradle.launcher.exec.ChainingBuildActionRunner.run(ChainingBuildActionRunner.java:35)
    at org.gradle.launcher.exec.InProcessBuildActionExecuter.execute(InProcessBuildActionExecuter.java:43)
    at org.gradle.launcher.exec.InProcessBuildActionExecuter.execute(InProcessBuildActionExecuter.java:28)
    at org.gradle.launcher.exec.ContinuousBuildActionExecuter.execute(ContinuousBuildActionExecuter.java:78)
    at org.gradle.launcher.exec.ContinuousBuildActionExecuter.execute(ContinuousBuildActionExecuter.java:48)
    at org.gradle.launcher.daemon.server.exec.ExecuteBuild.doBuild(ExecuteBuild.java:52)
    at org.gradle.launcher.daemon.server.exec.BuildCommandOnly.execute(BuildCommandOnly.java:36)
    at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
    at org.gradle.launcher.daemon.server.exec.WatchForDisconnection.execute(WatchForDisconnection.java:37)
    at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
    at org.gradle.launcher.daemon.server.exec.ResetDeprecationLogger.execute(ResetDeprecationLogger.java:26)
    at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
    at org.gradle.launcher.daemon.server.exec.RequestStopIfSingleUsedDaemon.execute(RequestStopIfSingleUsedDaemon.java:34)
    at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
    at org.gradle.launcher.daemon.server.exec.ForwardClientInput$2.call(ForwardClientInput.java:74)
    at org.gradle.launcher.daemon.server.exec.ForwardClientInput$2.call(ForwardClientInput.java:72)
    at org.gradle.util.Swapper.swap(Swapper.java:38)
    at org.gradle.launcher.daemon.server.exec.ForwardClientInput.execute(ForwardClientInput.java:72)
    at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
    at org.gradle.launcher.daemon.server.health.DaemonHealthTracker.execute(DaemonHealthTracker.java:47)
    at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
    at org.gradle.launcher.daemon.server.exec.LogToClient.doBuild(LogToClient.java:66)
    at org.gradle.launcher.daemon.server.exec.BuildCommandOnly.execute(BuildCommandOnly.java:36)
    at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
    at org.gradle.launcher.daemon.server.exec.EstablishBuildEnvironment.doBuild(EstablishBuildEnvironment.java:72)
    at org.gradle.launcher.daemon.server.exec.BuildCommandOnly.execute(BuildCommandOnly.java:36)
    at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
    at org.gradle.launcher.daemon.server.health.HintGCAfterBuild.execute(HintGCAfterBuild.java:41)
    at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
    at org.gradle.launcher.daemon.server.exec.StartBuildOrRespondWithBusy$1.run(StartBuildOrRespondWithBusy.java:50)
    at org.gradle.launcher.daemon.server.DaemonStateCoordinator$1.run(DaemonStateCoordinator.java:246)

This is the project where it happens (note Kodein is not added on master): https://github.com/autrilla/Farmnet-Android

Any ideas?

sugestions

Kodein is very sexy DI library, It will become a next spring in kotlin.
I have some sugestion:

  1. More flexible type matcher, eg. C > B > A, instance<A> and instance<B> also can get the instance of C
  2. Use annotation processor gernerate kodein module, less coding and less dependecy
  3. Auto Set. bind same type beans more times, retrieve it as Set. don't need bind inSet()

Access original instance from within overriding statement

In tests I want to wrap real object with some test logic and pass wrapped instance to application.

Now for this case, I also provide implementation of object and use it only in override-provider, so it looks like this:

// Module in real Application
...
bind<AvsDoActionExecutor>() with singleton {
    instance<AvsDoActionExecutorImpl>()
}

bind<AvsDoActionExecutorImpl>() with singleton {
    AvsDoActionExecutorImpl(
        // something
    )
}
// Module with override flag in test Application
...
bind<AvsDoActionExecutor>() with singleton {
    TestLogicWrapper(instance<AvsDoActionExecutorImpl>())
}

Are there ways to do it natively in Kodein 2.8.0? Is there any way to access original instance from within overriding statement?

Kodein in an Android Library

Hi,

I have been trying to build a android library using Kotlin and came across Kodein for DI. A lot of examples in the documentation are based on using it for an Android Application where we make the Application class KodeinAware. I am just curios if this works the same way even if I am creating and Android Library where I don't have an application class but a generic configuration class that will be called during the initialization phase of the Client that is going to use the library. The library will house Broadcast Receivers, Activities along with other generic classes.

I wanted to quickly ask this question before I go start hooking it up.

Clear Bindings

Is there a reason that clearing bindings is not possible? That way we could store things like Activity or Fragment in a Kodein and then when the Activity is done with it, clear the bindings.

I'm asking this because I have a need for binding Activity and Fragment instances which leads to memory leaks (as their CInstance lives in KodeinContainer after the Activity or Fragment is destroyed).

import and Module are too tightly coupled

import is tightly coupled to the Module class which is a final class. I would like to be able to define my own class to be imported primarily to be able to pass arguments to the class (e.g. pass the Android Application instance to the module).

import should not take a Module instance directly, it should take an interface that Module implements. What I would really love to be able to just say is that Module implements Kotlin.Builder.() -> Unit, but unfortunately extension function types cannot be used as supertypes.

So this is what seems to make sense to me. Define a Kodein.Import interface:

interface Import : () -> Kodein.Builder.() -> Unit

Then import would be changed to use that interface:

fun import(import: Import) = import().invoke(this)

Module then is only one possible implementation of the interface:

class Module(val init: Kodein.Builder.() -> Unit) : Import
{
    override fun invoke() = init
}

Then I could define my own class types to import:

class MyModule(val application: Application) : Kodein.Import
{
    override fun invoke() : Kodein.Builder.() -> Unit =
    {
        todo()
    }
}

which I can then use as:

import(MyModule(theApplication))

hwo to two parameter

data class User(private val name: String,
private val sex:String)

but this is error

private val kodein = Kodein {
bind() with factory { name: String, sex: String -> User(name, sex) }
}

hwo to work

Include sources in jars

Because there are no sources in the jars, opening Kodein classes in Android Studio just shows semi-decompiled kotlin:

// IntelliJ API Decompiler stub source generated from a class file
// Implementation of methods is not available

package com.github.salomonbrys.kodein.android

public val androidModule: com.github.salomonbrys.kodein.Kodein.Module /* compiled code */

@android.annotation.SuppressLint public fun autoAndroidModule(app: android.app.Application): com.github.salomonbrys.kodein.Kodein.Module { /* compiled code */ }

@android.annotation.SuppressLint private fun defineAndroidModule(): com.github.salomonbrys.kodein.Kodein.Module { /* compiled code */ }

"UninjectedException: Value has not been injected" after orientation change

When I use an kodein activity and and kodein fragment, the first start of the activity works perfect. But if i rotate the device, the fragment gets recreated before onCreate of the the activity is finished.

That means that the kodein value is not injected when the fragment needs it.

This could be easily fixed if in all kodein activities you call initializeInjector BEFORE super.onCreate(savedInstanceState)

-> a workaround for the moment is to use the interface versions and call this function in the activities yourself before super.onCreate(savedInstanceState)

override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        initializeInjector()
}

should be changed to

override fun onCreate(savedInstanceState: Bundle?) {
        initializeInjector()
        super.onCreate(savedInstanceState)
}

in KodeinActivity, KodeinFragmentActivity and KodeinAppCompatActivity

CompositeTypeToken problem

class KodeinTest {

    open class A<S>

    open class B<X> : A<X>()

    class C : B<String>()

    @Test
    fun test() {
        val t = CompositeTypeToken<B<String>>(erased(), TT(String::class.java))
        println(t.simpleDispString())
        val kodein = Kodein {
            bind<B<String>>() with provider { C() }
        }
        kodein.Instance<B<String>>(t)
    }
}

But I failed to retrieve an instance by composite type token

com.github.salomonbrys.kodein.Kodein$NotFoundException: No provider found for bind<KodeinTest.B<String>>() with ? { ? }
Registered in Kodein:
        bind<KodeinTest.B<String>>() with provider { KodeinTest.C } 
	at com.github.salomonbrys.kodein.KodeinContainer$DefaultImpls._notFoundException(KodeinContainer.kt:32)
	at com.github.salomonbrys.kodein.KodeinContainer$DefaultImpls.nonNullProvider(KodeinContainer.kt:75)
	at com.github.salomonbrys.kodein.internal.KodeinContainerImpl.nonNullProvider(KodeinContainerImpl.kt:17)
	at com.github.salomonbrys.kodein.Kodein$DefaultImpls.Instance(Kodein.kt:396)
	at com.github.salomonbrys.kodein.internal.KodeinImpl.Instance(KodeinImpl.kt:13)
	at com.github.salomonbrys.kodein.Kodein$DefaultImpls.Instance$default(Kodein.kt:396)
	at cn.org.cicada.mobile.ui.KodeinTest.test(KodeinTest.kt:24)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
	at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
	at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
	at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
	at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
	at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
	at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:117)
	at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:42)
	at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:262)
	at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:84)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)

Android Module and KodeinGlobal

I tried to imitate the bindings of android module in my Kodein Global. For example:

bind() from ProviderBinding(erased()) { ctx().getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager }

In order to avoid momory leak, I made it like this:

bind<ConnectivityManager >() with instance(this@MyApp.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager )

The code above didn't work, I print the bindings out and this binding exists, I also try to null-check the instance from Kodein.global and it is not null but when I try something like:

Kodein.global.instance<ConnectivityManager >().activeNetworkInfo.isConnected

my app crash and stack trace said that I tried to call these function on a null reference.

Howerver, when I change the code to this and explicitly cast it at retrieve time, it's ok:

bind<Any>("connectivity") with instance(this@MyApp.getSystemService(Context.CONNECTIVITY_SERVICE))

I don't know if I'm doing anything wrong. I wonder why it become null just when I call a function on it and not when I check if it is null. Another question is that if it is null at binding time, why does it run without yielding any error until I retrieve the faulty binding?

P/S: Sorry if I said something stupid (I just started with android recently) or any typo (English's not my native language). Hope someone help me with this or even make an android module exclusively for Kodein Global (of course, with some usage note to avoid leaking memory)

Inject generic type

Is it possible to inject an object of a generic type, for example:

class App : Application(), KodeinAware {

    override val kodein by Kodein.lazy {
        import(autoAndroidModule(this@App))

        bind<MainPresenter>() with autoScopedSingleton(androidActivityScope) { MainPresenter() }
    }

    override fun onCreate() {
        super.onCreate()
        registerActivityLifecycleCallbacks(androidActivityScope.lifecycleManager)
    }
}
class MainActivity : MvpActivity<MainPresenter, MainView>(), MainView {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        presenter.testMethod()
    }
}
abstract class MvpActivity<out P : MvpPresenter<V>, V : MvpView> : AppCompatActivity() {
    val kodein = LazyKodein(appKodein)
    val presenter: P by kodein.instance< ??? >()
}

Is it possible somehow to resolve that presenter dependency?

OverrideException print key to log

throw Kodein.OverridingException("Binding must not override an existing binding")

it will be nice to print key in log, like:

if (!mustOverride && key in _map)
  throw Kodein.OverridingException("Binding must not override an existing binding [key=$key]")

"No binding found" error by generic interface

Hi,

this library looks pretty good, so it's simple, powerful and quite Kotlin like.
However I encountered a problem when I try to inject a instance of generic interface.

Example code:

public interface Foo
public interface Bar<T>
public class FooBarImpl : Bar<Foo>

override val kodein: Kodein by lazyKodein {
    bind<Bar<Foo>>() with instance(FooBarImpl())
}

val foobar: Bar<Foo> by injectInstance() // "No binding found" exception!!

The instance of Kodein properly has the instance of FooBarImpl in its map, but binding failed.
I found an uncool solution using a wrapper interface:

public interface Foo
public interface Bar<T>
public interface FooBar : Bar<Foo>
public class FooBarImpl : FooBar

override val kodein: Kodein by lazyKodein {
    bind<FooBar>() with instance(FooBarImpl())
}

val foobar: FooBar by injectInstance()

It works well, but I am not a fan of the redundant interface.
Do you have any ideas for solving this issue?

Remove dependencies from Kodein-Android

I had to remove this dependencies for my project to compile again

compile('com.github.salomonbrys.kodein:kodein-android:2.1.0') {
    exclude module: 'support-v4'
    exclude module: 'android'
}

Take a look if this can be removed from the project, or add this lines on the import statement on the README

OverridingException: Binding bind<LayoutInflater>() with ? { ? } must not override an existing binding

Hi!

I tried to implement Kodein in a project and met a crash.
I started investigating... then I gave up.

Then I could reproduce it easily with the Kodein master branch.

I edited the android-demo sample project dependencies replacing:

  compile project(':kodein-core')
  compile project(':kodein')
  compile project(':kodein-android')

with:

  final KODEIN_VERSION = '3.2.0'
  compile "com.github.salomonbrys.kodein:kodein-core:$KODEIN_VERSION"
  compile "com.github.salomonbrys.kodein:kodein:$KODEIN_VERSION"
  compile "com.github.salomonbrys.kodein:kodein-android:$KODEIN_VERSION"

Am I missing something?

03-23 14:09:35.556 22623-22623/kodein.demo E/AndroidRuntime: FATAL EXCEPTION: main
                                                             Process: kodein.demo, PID: 22623
                                                             java.lang.RuntimeException: Unable to start activity ComponentInfo{kodein.demo/kodein.demo.MainActivity}: com.github.salomonbrys.kodein.Kodein$OverridingException: Binding bind<LayoutInflater>() with ? { ? } must not override an existing binding.
                                                                 at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2665)
                                                                 at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2726)
                                                                 at android.app.ActivityThread.-wrap12(ActivityThread.java)
                                                                 at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1477)
                                                                 at android.os.Handler.dispatchMessage(Handler.java:102)
                                                                 at android.os.Looper.loop(Looper.java:154)
                                                                 at android.app.ActivityThread.main(ActivityThread.java:6119)
                                                                 at java.lang.reflect.Method.invoke(Native Method)
                                                                 at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886)
                                                                 at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776)
                                                              Caused by: com.github.salomonbrys.kodein.Kodein$OverridingException: Binding bind<LayoutInflater>() with ? { ? } must not override an existing binding.
                                                                 at com.github.salomonbrys.kodein.KodeinContainer$Builder._checkOverrides(KodeinContainer.kt:246)
                                                                 at com.github.salomonbrys.kodein.KodeinContainer$Builder.access$_checkOverrides(KodeinContainer.kt:137)
                                                                 at com.github.salomonbrys.kodein.KodeinContainer$Builder$BindBinder.with(KodeinContainer.kt:297)
                                                                 at com.github.salomonbrys.kodein.Kodein$Builder$TBuilder$TypeBinder.with(Kodein.kt:189)
                                                                 at com.github.salomonbrys.kodein.android.ActivityInjector$initializeInjector$activityModule$1.invoke(KodeinAndroidComponents.kt:85)
                                                                 at com.github.salomonbrys.kodein.android.ActivityInjector$initializeInjector$activityModule$1.invoke(KodeinAndroidComponents.kt:75)
                                                                 at com.github.salomonbrys.kodein.Kodein$Builder.<init>(Kodein.kt:303)
                                                                 at com.github.salomonbrys.kodein.Kodein$Builder.import(Kodein.kt:387)
                                                                 at com.github.salomonbrys.kodein.android.KodeinAndroidComponentsKt$inject$kodein$1.invoke(KodeinAndroidComponents.kt:21)
                                                                 at com.github.salomonbrys.kodein.android.KodeinAndroidComponentsKt$inject$kodein$1.invoke(KodeinAndroidComponents.kt)
                                                                 at com.github.salomonbrys.kodein.Kodein$Builder.<init>(Kodein.kt:303)
                                                                 at com.github.salomonbrys.kodein.internal.KodeinImpl.<init>(KodeinImpl.kt:34)
                                                                 at com.github.salomonbrys.kodein.Kodein$Companion.invoke(Kodein.kt:469)
                                                                 at com.github.salomonbrys.kodein.Kodein$Companion.invoke$default(Kodein.kt:469)
                                                                 at com.github.salomonbrys.kodein.android.KodeinAndroidComponentsKt.inject(KodeinAndroidComponents.kt:18)
                                                                 at com.github.salomonbrys.kodein.android.KodeinAndroidComponentsKt.access$inject(KodeinAndroidComponents.kt:1)
                                                                 at com.github.salomonbrys.kodein.android.ActivityInjector$DefaultImpls.initializeInjector(KodeinAndroidComponents.kt:90)
                                                                 at com.github.salomonbrys.kodein.android.KodeinActivity.initializeInjector(KodeinAndroidComponents.kt:103)
                                                                 at com.github.salomonbrys.kodein.android.KodeinActivity.onCreate(KodeinAndroidComponents.kt:109)
                                                                 at kodein.demo.MainActivity.onCreate(MainActivity.kt:26)
                                                                 at android.app.Activity.performCreate(Activity.java:6679)
                                                                 at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1118)
                                                                 at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2618)
                                                                 at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2726) 
                                                                 at android.app.ActivityThread.-wrap12(ActivityThread.java) 
                                                                 at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1477) 
                                                                 at android.os.Handler.dispatchMessage(Handler.java:102) 
                                                                 at android.os.Looper.loop(Looper.java:154) 
                                                                 at android.app.ActivityThread.main(ActivityThread.java:6119) 
                                                                 at java.lang.reflect.Method.invoke(Native Method) 
                                                                 at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886) 
                                                                 at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776) ```

Multiton bindings for jx @Inject field

For any KodeinInjected class it is safe to use fileds like

val logger: AppLogger by withClass().instance()

with proper multiton bindind like

bind<AppLogger>() with multiton { cls: Class<*> -> AppLogger(cls.simpleName) }

but i can't find solution to get multiton bindings for jx injections for simple POJO classes like

class Worker {
   @Inject lateinit var logger: AppLogger
}

I am trying

val worker=Worker()
kodein.jx.inject(worker)

and got an exception

...
No provider found for bind<AppLogger>() with ? { ? }
    Registered in Kodein:
        bind<AppLogger>() with multiton { Class<*> -> AppLogger } 
....

Is there any workaround?

Fragments should use the parent fragment's injector as the parent when possible

As of Android API 17 (Jelly Bean MR1), a Fragment can contain another Fragment. It makes sense for cases where a FragmentInjector has a parentFragment that it's injector is used as the parent instead of the Activity.

The specific issue I encountered was a parent Fragment was providing additional bindings in provideOverridingModule that were not present in the child Fragment.

Add support for testing injection.

Hi, I'm trying to write some espresso tests with Kotlin and using Kodein for DI. The technique I'm using is based on the replacement of production code using test doubles.

When using Kodein from my instrumentation tests everything works like a charm. If I replace the application graph with a custom one before the test is executed and every dependency is provided before the test activity is launched everything works as expected. This is working because I can replace the application module using one created from my test. But I've found a problem when the module used is initialized from the activity and not from the application. Here you have an initialization example when running a test:

The application starts: the app module is configured and initialized.
The test starts: My test module, configured with some test doubles, is added.
The activity is initialized: The activity modules are added to the graph.

Expected result: The graph does not replace the already configured dependencies using a test double.
Actual result: If I use the "override" param I lost my test module provision because the dependency has been replaced with the new one. If I remove the "override" param the app crashes.

I'd like to propose a feature request where by configuration we could allow a silent injection that doesn't apply the override and does not throw any exception. If you are ok with this new feature I can send a pull request.

I'd really like to resolve this issue even if you think there is a better approach. We can use this issue to talk about and after that send a PR :)

I found a tricky solution that allows to me fix this problem but I adding coding in production related with the tests and this is not the best solution.

if you like to view our approach for Java code you can read this blog post http://blog.karumi.com/world-class-testing-development-pipeline-for-android-part-4/

Thanks for your time and this awesome library!

Support and/or make clear how to make bindings via reflection

We have a REST API implemented with DropWizard. It uses the resource/repository pattern. We currently aren't using any DI, which is starting to get rather hairy as we keep adding more. I've been experimenting using Kodein, and had hoped that I could use reflection to dynamically find all classes that inherit from our Repository/Resource interfaces and set bindings dynamically.

        val kodein = Kodein {
            val reflections = Reflections("com.stuff.api")

            bind() from setBinding<Resource>()

            val resourceClasses = reflections.getSubTypesOf(Resource::class.java).filter { !Modifier.isAbstract(it.modifiers) }
            for (resourceClass in resourceClasses) {
                // doesn't work
                bind() from singleton { resourceClass.getConstructor(Kodein::class.java).newInstance(kodein) }
                bind<Resource>().inSet() with provider { kodein.Instance(TT(resourceClass)) }
            }
        }

The problem with the line under the comment is that the binding is made to Resource instead of the specific T that resourceClass represents, so the second iteration of the loop causes an exception. I found Bind(TypeToken) and started trying something like

for (resourceClass in resourceClasses) {
    val typeToken = TT(resourceClass)
    Bind(typeToken). // what now?
}

The problem, though, is that all of the implementations of the Binding interface take a type parameter, which I can't provide because of using reflection.

Maybe I'm missing something, and there's a better way to go about this? I'd really just like to avoid needing to write this for each of our dozens of resources:

bind() from singleton { FooResource(kodein) }
bind<Resource>().inSet() with provider { kodein.instance<FooResource>() }

Recreate a kodein instance

Is there any way to “restart/recreate” the kodein instance ? in order to recreate the singleton .
Is the solution to use Configurable Kodein ?

Here’s an example :
I have a binding that will inject an ApiService that allows me to call webservices. But this object need to be initialized with a BaseUrl :
bind<ApiService>() with singleton {ApiService(url)}
Unfortunatelly, in my app, this url can be change at runtime. So I’ll need to “restart” kodein from scratch (or the network module ?)
Is this possible with a Kodein.lazy property ? or do I need to use a ConfigurableKodein for that ?

Android Scopes Need to Be Cast To Base Class When Retrieving

If I have the following Activity

class TestActivity : Activity() {
  val kodein = Kodein {
    bind<Any>() with activitySingleton { Any() }
  }

  private val any1: Any = kodein.with(this).instance()
  private val any2: Any = kodein.with(this).instance()

  override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)

    Log.e("TEST", "$any1 $any2")
  }
}

I get an error:

java.lang.RuntimeException: Unable to instantiate activity ComponentInfo{com.test/com.test.TestActivity}: com.github.salomonbrys.kodein.Kodein$NotFoundException: No factory found for bind() with ? { TestActivity -> ? }
Registered in Kodein:
bind() with scopedSingleton(activityScope) { Activity -> Object }

If I change the retrieval to:

  private val any1: Any = kodein.with(this as Activity).instance()
  private val any2: Any = kodein.with(this as Activity).instance()

it works.

Currying a factory with a more specific type

Using 3.0.0-beta6.

I have the following binding:

bind() from factory { element: Element ->
   EntityRelatedNameBuilder(kodein, element)
}

And when I do the following, I got a Kodein.NotFoundException:

val names: EntityRelatedNameBuilder = with(element /* a TypeElement that is a subtype of Element */)
   .instance()

Isn't this supposed to work properly? I had to add an explicit type parameter to the with as follows:

val names: EntityRelatedNameBuilder = with<Element>(element).instance()

Can't inject in a service

I am new to Kodein, so maybe I am doing something wrong.
I have a service where I implement the KodeinInjected and in onCreate inject the inject(appKodein())
I try to call an instance of val sharedPrefs: SharedPreferences by withContext(this).instance()
but I get a null pointer java.lang.NullPointerException: Attempt to invoke virtual method 'com.github.salomonbrys.kodein.KodeinInjector$TInjector com.github.salomonbrys.kodein.KodeinInjector.getTyped()' on a null object reference
How can I import my dependency in a service considering this works in an activity already.
Thx. And by the way awesome library. We are using it in production already.

Support for custome scopes

Please add support for custome scopes. Now there is possibility to implement custome scope but ot would be nice to have some generic mechanism to use scopes just by define some scope identifier.

Compiles and works with Javascript?

Hi!

I'm looking for a injection-like framework for Kotlin that would compile to Javascript.

Does your "Kodein" framework do that?

Regards,
Jørund

Type inference failed using KodeinGlobalAware or KodeinAware but not with KodeinInjected

Hi!

I'd like to use KodeinGlobalAware in my Android application as described here (though the docs differ from the actual implementation required). I feel it's use case fits perfectly for my situation.

When I create a class:

class MyClass : KodeinGlobalAware {
   val garfield : Cat by with("I hate Mondays").instance()
}

the compiler gives me an error on instance()

Type inference failed: Not enough information to infer parameter T in
  inline fun<reified T: Any> CurriedKodeinFactory<*>.instance(tag : Any? =...) : T
Please specify it explicitly

This error does not occur when I make the class KodeinInjected

The binding for this class I'd like to inject looks like
bind<Cat>() with factory { catchphrase: String -> Cat(catchphrase) }

I've tried passing type information to instance() with instance<Cat>() but that only produces another, different error

missing 'getValue(Cat, KProperty<*>)' method on delegate of type 'Cat'

This behavior also happens when using KodeinAware instead of KodeinGlobalAware.
What gives?

Can Kodein bind a factory with more than one argument?

Hello!

I'd like to bind a factory in my KodeinModule.
I'd also like this factory to take arguments.

I have successfully created a factory that takes one argument, but when I try to add more the compiler complains that there's no with that takes varargs.

The code that produced that error looks something like the following:

Binding

bind<Cat>() with factory { name: String, color: String, hatesMondays: Boolean ->
    Cat(name, color, hatesMondays)
}

Using

class Comic : KodeinGlobalAware {
  val garfield: Cat = with("Garfield", "Orange", true).instance()
}

With the error appearing on the first line of the above code snippet.

What can I do to create a factory that takes multiple arguments?

Android: KodeinInjector and appKodein()

On Android, Is it possible to implement KodeinInjector on a class that does not extend from any other Android class such as Activity, Fragment, etc?

To give this question more context: I use an MVP architecture, so my Presenter does not implement/extend anything Android related (thus increasing testability). Normally Presenters would be the most "injected" classes since they're in charge of all the business logic, so, I was wondering if there's a way of injecting those presenters using Kodein. So far I tried with a KodeinInjector, but I have no access to appKodein nor the Kodein instance declared in the Application class.

Binding instances aren't properly initialized after Fragment recreation

I'm using 2.3.0 but this issue was present in earlier versions as well.

If I have a binding in the androidSupportFragmentScope, and the Fragment used with that scope has a child fragment, then in that binding calling instance<Fragment>() returns the child Fragment, while calling (it as KodeinInjected).kodein().value.instance<Fragment>() correctly returns the parent Fragment.

Cannot override an existing binding with a mock in tests

I'm trying to use Kodein to inject a mock service into a test class, but I get the error:

com.github.salomonbrys.kodein.Kodein$OverridingException: Binding bind<UserService>() with ? { ? } must override an existing binding.

My test class attempts to override the injection:

class UserControllerTest {
	val controller = UserController()
	val mockUserService = mock<UserService> {
		on { getAllUsers() } doReturn emptyList<User>()
	}
	init {
		println("INIT: bindings: " + controller.injectService.container.bindings.fullDescription)
		println("INIT: overriding injectService")
		controller.injectService = Kodein {
			bind<UserService>(overrides = true) with provider { mockUserService }
		}
	}

      @Test
	fun testMockUserServiceReturnsNoUsers() {
		println("GETALL: bindings: " + controller.injectService.container.bindings.fullDescription)
		val result = controller.userService.getAllUsers()
		println("GETALL: result: " + result)
		Assert.assertTrue(result.isEmpty())
	}
}

The println statements show that there is an existing binding. Here is the full output:

INIT: bindings:         bind<uk.co.liamjdavison.kotlinsparkroutes.services.users.UserService>() with provider { uk.co.liamjdavison.kotlinsparkroutes.services.users.InMemoryUserService } 
INIT: overriding injectService

com.github.salomonbrys.kodein.Kodein$OverridingException: Binding bind<UserService>() with ? { ? } must override an existing binding.

So there clearly is an existing binding to InMemoryUserService.

Have I completely misunderstood the overrides?

If I don't try to override, I get the following output:

INIT: bindings:         bind<uk.co.liamjdavison.kotlinsparkroutes.services.users.UserService>() with provider { uk.co.liamjdavison.kotlinsparkroutes.services.users.InMemoryUserService } 
INIT: overriding injectService
GETALL: bindings:         bind<uk.co.liamjdavison.kotlinsparkroutes.services.users.UserService>() with provider { uk.co.liamjdavison.kotlinsparkroutes.services.users.UserService } 
GETALL: result: [User(name=Liam, age=38)]

Which is wrong, because the mockUserService is told to return an empty list, and the values [User(name=Liam, age=38)] definitely come from InMemoryUserService.

Question: Providing context to nested injection

bind<FirebaseAnalytics>() with factory { ctx: Context -> FirebaseAnalytics.getInstance(ctx) }
bind<Tracker>() with singleton { FireBaseTracker(instance()) }

Code above does not work obviously, with and without context.

but i still want to inject Tracker via singleton, using ApplicationContext, how i could do it in this situation? is it possible?

Unclear on the use the `jx` module

I am have bound services needing other bound services.

My binding looks like this:

val kodein = Kodein {
    import(jxInjectorModule)
    bind<Properties>() with singleton { PropertiesLoaderUtils.loadProperties(ClassPathResource("application.properties")) }
    bind<FileContentProvider>() with singleton { FileContentProvider.default }
    bind<DistributionService>() with singleton { jx.newInstance<DistributionServiceImpl>() }
    bind<InnkeeperClient>() with singleton { jx.newInstance<InnkeeperClientImpl>() }
    bind<QuiltClient>() with singleton { jx.newInstance<QuiltClientImpl>() }
    bind<TessellateClient>() with singleton { jx.newInstance<TessellateClientImpl>() }
    bind<JsonService>() with singleton { JsonServiceImpl() }
    bind<RequestContext>() with singleton { RequestContextImpl() }
    bind<Authorization>() with singleton { AuthorizationImpl() }
}

The moment I hit the resolving of the DistributionService, it fails with this message:

com.github.salomonbrys.kodein.Kodein$DependencyLoopException: Dependency recursion:
       ╔═> bind<JxInjector>()
       ╠─> bind<DistributionService>()
       ╚═> bind<JxInjector>()

The constructor of my DistributionServiceImpl is:

class DistributionServiceImpl(
    private val jsonService: JsonService,
    private val properties: Properties,
    private val quiltClient: QuiltClient,
    private val innkeeperClient: InnkeeperClient,
    private val tessellateClient: TessellateClient
) : DistributionService {

When I debug with breakpoints in every one of the singleton lambda, I observe that the following are called:

  • JsonServiceImpl()
  • FileContentProvider.default
  • jx.newInstance<DistributionServiceImpl>()
    Then it fails before entering the constructor of class DistributionServiceImpl.

I feel that I simply am not using this right. However, the documentation does not state a clear example of how to declare a binding block using the jx approach. It just states as an example:

val kodein = Kodein {
    import(jxInjectorModule)
    /* Other bindings */
}

I am interested in HOW to declare the other bindings here.

Thanks for whatever help you can provide.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.