Code Monkey home page Code Monkey logo

koin's People

Contributors

amaksoft avatar arnaudgiuliani avatar cortinico avatar dcvz avatar erickok avatar fredy-mederos avatar grzegorzbobryk avatar gzaccaroni avatar igorwojda avatar istvankovacs-priv avatar johnjohndoe avatar jschmid avatar kamo030 avatar kedzie avatar kpgalligan avatar marcellogalhardo avatar mpontus avatar octa-one avatar pedrofsn avatar pfoerd avatar pitel avatar qwert2603 avatar rajkiran20 avatar remvst avatar shalomhalbert avatar tynn avatar uoooo avatar viniciusccarvalho avatar wiryadev avatar ychescale9 avatar

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  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

koin's Issues

View model injection

Hi. I like where v0.8.0 is going with adding an API for view model injection. However, there are some things I noted.

  1. I cannot inject the view model in the normal manner

    private val viewModel: MyViewModel by inject()
  2. I have to manually pull the activity or parent fragment in order to use shared view models.

    val viewModel = activity.getViewModel<MyViewModel>()

    For an activity, it is straightforward. However, for a parent fragment it is more complicated.

  3. Configuring the koin context with viewModel {} makes it look like nested contexts should inject/get the same instance of the view model as the parent context. This could be confusing to people who have not read the underlying code.


Presently, I have a different approach which hides the ViewModelProvider behind the koin context and allows for lazy injection.

This approach does require the context to be initiated in Fragment::onCreate or Activity::onCreate. Also, the ViewModels are KoinComponents eliminating constructor injection and negating the need for providing a custom ViewModelFactory.

/**
 * Main activity using view model injection with initialisation of koin context in onCreate.
 */
class MainActivity: FragmentActivity() {
    private val navigation: NavigationViewModel by inject()

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

        setProperty(Context.Activity, this)
    }
}

/**
 * Home fragment injecting navigation view model which is shared with activity.
 */
class HomeFragment: Fragment() {
    private val navigation: NavigationViewModel by inject()
    private val viewModel: HomeViewModel by inject()

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

        setProperty(Context.HomeFragment, this)
    }
}

/**
 * Context string constants.
 */
object Context {
    const val Activity = "Activity"
    const val HomeFragment = "HomeFragment"
}

/**
 * Get list of app modules for startKoin.
 */
fun appModules() = listOf(appModule)

/**
 * Koin application module.
 */
private val appModule = applicationContext {
    context(Activity) {
        viewModel<NavigationViewModel>()

        context(HomeFragment) {
            viewModel<HomeViewModel>()
        }
    }
}

/**
 * Add a view model to the context.
 * 
 * @param scopeType Scope type of ViewModelProvider. If not set an attempt will be made to determine it at runtime.
 * @param name Name of property scope object is set within. Default is same as context.
 */
private inline fun <reified T : ViewModel> Context.viewModel(
        scopeType: ScopeType? = null,
        name: String = this.name
) = when (name) {
    Scope.ROOT -> throw CantInjectViewModelException()
    else       -> factory {
        when (scopeType) {
            ScopeType.Activity -> ViewModelProviders.of(getActivity()).get(T::class.java)
            ScopeType.Fragment -> ViewModelProviders.of(getFragment()).get(T::class.java)
            null               -> try {
                ViewModelProviders.of(getActivity()).get(T::class.java)
            } catch (e: ClassCastException) {
                try {
                    ViewModelProviders.of(getFragment()).get(T::class.java)
                } catch (e: ClassCastException) {
                    throw CantInjectViewModelException()
                }
            }
        }
    }
}

sealed class ScopeType {
    object Activity : ScopeType()
    object Fragment : ScopeType()
}

private class CantInjectViewModelException :
        IllegalStateException("Injecting view model requires associated Fragment or FragmentActivity.")

private inline fun Context.getActivity(name: String = this.name) = getProperty<FragmentActivity>(name)
private inline fun Context.getFragment(name: String = this.name) = getProperty<Fragment>(name)

Inject using current Android Context

Hello I'm wondering simply if there is a way to inject an Activity or while using either it's context or the Application object to initialize the object.

So something like:

class HomeActivity : Activity() {
    override val contextAwareObject by inject<ThisObjectNeedsContextInConstructor>()
}

I've tried using get() for the context in a module but it doesn't seem to be able to do the trick since it only has access to a Koin Context, not an Android one. I have seen an example using an AndroidModule but it seems I can't find an AndroidModule in the current version.

In particular I'm trying to inject access to my database, which is currently initialized and owned by the Application class. It needs an App context to start. So therefore my Activities have to know about it even though I'm using MVP. It would be really nice if when I inject my presenter I could also inject the presenter by constructor with the database object.

FragmentStatePagerAdapter injection

Hi guys, I need some help with injecting of state pager adapter.
I do it like this now:

class AppModule : AndroidModule() {
    override fun context() = applicationContext {
        context(name = CTX_CANVAS_ACTIVITY) {
            provide { MainPagerAdapter(getProperty(MainActivity.FRAGMENT_MANAGER_KEY), getProperty(MainActivity.FRAGMENT_NAMES_KEY)) }

And in MainActivity

private val pagerAdapter by inject<MainPagerAdapter>()
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        getKoin().setProperty(FRAGMENT_MANAGER_KEY, supportFragmentManager)
        getKoin().setProperty(FRAGMENT_NAMES_KEY, resources.getStringArray(R.array.main_view_pager_items))

However after orienation change I get an IllegalStateException like no fragment for the key. What is the right way to do such injection? Thanks in advance.

Bean implements multiple interfaces. How to inject only some of them?

There is a case:
interface Repo { interface RO {} interface RW: RO {} }

bean { RepoImpl() as Repo.RW}

class UserCaseA(val repoRW: Repo.RW)
bean {UseCaseA(get())} - Works

class UseCaseB(val repoRO: RepoRO)
bean {UseCaseB(get())} - Fails. It's clear why is fails.

But is there any simple way to get it's working?
The main point is to create and keep only ONE instance of RepoImpl().

License is not valid

Hi @arnaudgiuliani,

I just looked into your DI lib and I noticed you license file is missing your name and the year, which makes it invalid.

But, this details, apart. I would be interested in chatting with you if you are interested. I am one of the authors of toothpick and I would like to understand better a few things about the way kotlin and koin work. I would have written an email to you but I couldn't find it on the net. Mine is much either to find. If you are interested, just send me an email.

Cheers,
S.

Type inference failed while attempting to inject ViewModel

I believe I have followed the docs correctly, but I can't seem to get this working.

I have an activity:

class LoginActivity : BaseActivity() {
    val viewModel: LoginViewModel by getViewModel()
. . .

And I am instantiating my module in my Application class:

val myModule : Module = applicationContext {
            . . . .
            viewModel { MyViewModel(get()) }
}
startKoin(this, listOf(myModule))

but I'm getting a compile error on the by getViewModel() line:

Type inference failed: Not enough information to infer parameter T in intline fun <reified T : ViewModel> FragmentActivity.getViewModel(): T
Please specify it explicitly

If I attempt to specify it via getViewModel<MyViewModel>(), I get this compile error:

Missing 'getValue(MyActivity, KPropery<*>)' method on delegate of type 'MyViewModel'

Or if I try:

val viewModel = getViewModel<LoginViewModel>()

I get a runtime NPE when the ViewModel can't get any instance correctly:

Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.app.Application.registerActivityLifecycleCallbacks(android.app.Application$ActivityLifecycleCallbacks)' on a null object reference
                                                       at android.arch.lifecycle.HolderFragment$HolderFragmentManager.holderFragmentFor(HolderFragment.java:169)
                                                       at android.arch.lifecycle.HolderFragment.holderFragmentFor(HolderFragment.java:84)
                                                       at android.arch.lifecycle.ViewModelStores.of(ViewModelStores.java:47)
                                                       at example.MyActivity.<init>(LoginActivity.kt:45)
                                                       at java.lang.Class.newInstance(Native Method)
                                                       at android.app.Instrumentation.newActivity(Instrumentation.java:1174)
                                                       at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2669)

Any insights would be greatly appreciated!

koinContext has not been initialized

Implemented everything similar to the wiki and got this error:

                                                                             java.lang.RuntimeException: Unable to start activity ComponentInfo{com.youtube.tedho.kotlinyoutube/com.youtube.tedho.kotlinyoutube.MainActivity}: kotlin.UninitializedPropertyAccessException: lateinit property koinContext has not been initialized

[Contributor needed] UI testing with ViewModels

Hello, @arnaudgiuliani !

Thank you for a great DI library. Starting using it and need some help with testing.

I have Android project with architecture components. I inject ViewModel using lazy 'by viewModel()' method. Inside ViewModel I have a repository that goes to API. Now I want to write UI tests for my app using Espresso. Obviously, I don't need real calls to the Internet, I want mocked data returned using Mockito.
And now I'm confused in what direction I should go. I read article about testing in documentation. But still can't figure out how to inject mocked repository inside my ViewModel for Espresso test.

Will appreciate any help.
Thanks.

java.lang.NoClassDefFoundError: java.util.concurrent.ConcurrentHashMap$KeySetView

Hi,

This is a great library. However I am getting the following error after the update to 0.8.1, if I run in a device with SDK 16:

E/AndroidRuntime: FATAL EXCEPTION: main java.lang.NoClassDefFoundError: java.util.concurrent.ConcurrentHashMap$KeySetView at org.koin.core.instance.InstanceFactory.findInstance(InstanceFactory.kt:45) at org.koin.core.instance.InstanceFactory.retrieveInstance(InstanceFactory.kt:27) at org.koin.KoinContext.resolveInstance(KoinContext.kt:70) at com.murselturk.radyo7.ui.base.BaseActivity$$special$$inlined$inject$1.invoke(AndroidExt.kt:106) at kotlin.SynchronizedLazyImpl.getValue(Lazy.kt:131)

Any ideas what to do?
Thanks.

How to inject a fragment/activity? (circular dependency)

Hey!

This is not your typical situation but please humour me :)

How can an activity/application/fragment be injected as a dependency?

Assuming I have a class AudioPlayer:

class AudioPlayer(private val context: Activity) {
    fun doToast() {
        Toast.makeText(context, "Running Audio player...", Toast.LENGTH_SHORT).show()
    }
}

Which I'll need to inject inside MainActivity:

class MainActivity : BaseActivity() {
    override val contextName = "MainActivity"

    val audioPlayer by inject<AudioPlayer>()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_layout)

        audioPlayer.doToast()
    }
}

How would I provide MainActivity as a dependency for AudioPlayer?

Here is the app module class:

fun appModules() = listOf(applicationModule())

class applicationModule : AndroidModule() {
    override fun context() = applicationContext {
        context(name = "MainActivity") {
            provide { AudioPlayer(get()) }
        }
}

Is there inject resolution collision in sub contexts

What happens if two sub contexts both have beans which satisfy an inject request?

val KoinModule = applicationContext {
  context("foo") {
    provide { wombat() } bind Animal::class
  }

  context("bar") {
    provide { koala() } bind Animal::class
  }
}

class Pojo {
   val animal: Animal = inject() 
}

Error: Can not create Bean Factory for Interface

Error when inject Retrofit Interface in ViewModel

Caused by: org.koin.error.BeanInstanceCreationException: Can't create bean Factory[class=br.com.disapps.simplemvvm.ui.main.MainViewModel, binds~(android.arch.lifecycle.ViewModel)] due to error :
                                               	org.koin.error.BeanInstanceCreationException: Can't create bean Bean[class=br.com.disapps.simplemvvm.api.IRestApi]

Set custom logger before startKoin() in Android

Is there any way to set custom Logger for koin before startKoin in android App?
Or maybe set Logger as a parameter for startKoin.
Main issue with current AndroidLogger() is that it's set in Application.startKoin() and make visible all KOIN logs to everyone in release builds.

Different fragment in a ViewPager with the same ViewModel.

I have a view model VMMain

class VMMain: ViewModel() {

    private var pendingList = MutableLiveData<List<String>>()
    var filteredPendingList: LiveData<List<String>> = Transformations.map(pendingList, { it })

    var list = listOf("Hello", "Where", "Are", "You", "From", "It's", "Lonely", "Here")

    fun filterList(searchString: String = "") {
        if (searchString.isEmpty()) {
            pendingList.value = list
        } else {
            pendingList.value = list.filter { it.contains(searchString, true) }
        }
    }
}

Then, I have a ViewPager with 2 fragments (fragment A & fragment B), each fragment use the above ViewModel VMMain & is initiated using

val vmMain by viewModel<VMMain>()

Using Koin, when I call vmMain.filterList("e") in fragment A, the vmMain in fragment B also got triggered. I believe this is a bug. Because the behaviour should be the triggered view model should only be in fragment A. When I initiate the viewModel using ViewModelProviders.of(this).get(VMMain::class.java), it works fine.

I created a simple project to prove my point : https://github.com/hidrodixtion/KoinViewModelReport

Injecting mocks

I was wondering if its possible to inject custom mocks to a class overloaded with KoinComponent?

So a class like MyViewModel.kt:

class GridViewModel
    : ViewModel(), KoinComponent {
    private val postRepository by inject<PostRepository>()
...
}

would have postRepository to be injectable when writing a test as such

class GridViewModelTest : KoinTest {
    lateinit var mockPostRepository: PostRepository
    lateinit var gridViewModel: GridViewModel

    @Before
    fun init() {
        mockPostRepository = mock()

        // Basically have `mockPostRepository` to be the injected postRepository from Koin
        gridViewModel = KoinInjector<GridViewModel>(mockPostRepository)
    }
}

Any idea how to do such a task?

Much appreciated!

Stackoverflow when calling getKoin in custom view

I have a weird exception when getKoin() is recursivly being called until Stackoverflow exception. It happens when I try to get the instance in my custom view via context.getKoin().get<T>. What can be the source of the issue?

provide(isSingleton = true)

I am trying to share a presenter between an Android Activity and a Fragment, and am using ContextAwareActivity/ContextAwareFragment, with the same context name. However, the 'by inject' of the presenter object is creating multiple instances (even though I'm specifyig isSingleton in provide).

org.koin.error.NoBeanDefFoundException: Multiple definition found for class

Hi,

I have an issue with Koin library, after following all initialization steps, I used it for several weeks and worked like a charm, until now...

I recently observed that one of my dependency is not longer injected, so I update my Koin version from 0.7.0-alpha-1 to 0.8.1-alpha-7. It didn't change anything....

It became even worse with this version, my application crash now and I receive this message : "Multiple definition found for class" . However my class is added once...

01-17 09:11:51.555 3695-3695/my.app.package I/KOIN: [init] declare : Bean[class=my.app.package.network.redesign.room.VDatabase, binds~(my.app.package.network.redesign.room.VDatabase)] 01-17 09:11:51.556 3695-3695/my.app.package I/KOIN: [init] declare : Bean[class=my.app.package.network.redesign.api.ProductService, binds~(my.app.package.network.redesign.api.ProductService)] 01-17 09:11:51.556 3695-3695/my.app.package I/KOIN: [init] declare : Bean[class=my.app.package.network.redesign.api.UserService, binds~(my.app.package.network.redesign.api.UserService)] 01-17 09:11:51.556 3695-3695/my.app.package I/KOIN: [init] declare : Bean[class=my.app.package.network.redesign.api.CommentService, binds~(my.app.package.network.redesign.api.CommentService)] 01-17 09:11:51.556 3695-3695/my.app.package I/KOIN: [init] declare : Bean[class=my.app.package.network.redesign.api.StaticService, binds~(my.app.package.network.redesign.api.StaticService)] 01-17 09:11:51.557 3695-3695/my.app.package I/KOIN: [init] declare : Bean[class=my.app.package.network.apis.VcProductApiService, binds~(my.app.package.network.apis.VcProductApiService)] 01-17 09:11:51.558 3695-3695/my.app.package I/KOIN: [init] declare : Bean[class=my.app.package.network.apis.VcNegotiationApiService, binds~(my.app.package.network.apis.VcNegotiationApiService)] 01-17 09:11:51.558 3695-3695/my.app.package I/KOIN: [init] loaded 7 definitions 01-17 09:11:51.558 3695-3695/my.app.package I/KOIN: [init] Load Android features 01-17 09:11:51.573 3695-3695/my.app.package I/KOIN: [Properties] no assets/koin.properties file to load 01-17 09:11:51.573 3695-3695/my.app.package I/KOIN: [init] ~ added Android application bean reference 01-17 09:11:53.613 3695-3695/my.app.package E/AndroidRuntime: FATAL EXCEPTION: main Process: my.app.package, PID: 3695 org.koin.error.NoBeanDefFoundException: Multiple definition found for class class my.app.package.network.redesign.api.StaticService : [Bean[class=my.app.package.network.redesign.api.StaticService, binds~(my.app.package.network.redesign.api.StaticService)]] [Bean[class=my.app.package.network.redesign.api.StaticService, binds~(my.app.package.network.redesign.api.StaticService)]] at org.koin.core.bean.BeanRegistry.searchAll(BeanRegistry.kt:87) at my.app.package.application.StaticContentProvider$$special$$inlined$inject$1$1.invoke(KoinContext.kt:48) at my.app.package.application.StaticContentProvider$$special$$inlined$inject$1$1.invoke(KoinContext.kt:20) at org.koin.KoinContext.resolveInstance(KoinContext.kt:65) at my.app.package.application.StaticContentProvider$$special$$inlined$inject$1.invoke(KoinComponent.kt:89) at kotlin.SynchronizedLazyImpl.getValue(Lazy.kt:130) at my.app.package.application.StaticContentProvider.getService(StaticContentProvider.kt) at my.app.package.application.StaticContentProvider.access$getService$p(StaticContentProvider.kt:16) at my.app.package.application.StaticContentProvider$reloadData$1.doResume(StaticContentProvider.kt:36) at my.app.package.application.StaticContentProvider$reloadData$1.invoke(StaticContentProvider.kt) at my.app.package.application.StaticContentProvider$reloadData$1.invoke(StaticContentProvider.kt:16) at my.app.package.network.utils.RxExtensionKt$start$2.doResume(RxExtension.kt:24) at kotlin.coroutines.experimental.jvm.internal.CoroutineImpl.resume(CoroutineImpl.kt:54) at kotlinx.coroutines.experimental.DispatchTask.run(CoroutineDispatcher.kt:123) at android.os.Handler.handleCallback(Handler.java:739) at android.os.Handler.dispatchMessage(Handler.java:95) at android.os.Looper.loop(Looper.java:135) at android.app.ActivityThread.main(ActivityThread.java:5254) at java.lang.reflect.Method.invoke(Native Method) at java.lang.reflect.Method.invoke(Method.java:372) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)

Injecting Room Databases

Hello, I have an abstract class named AppDatabase, which inherits from RoomDatabase. I am trying to use Koin to provide AppDatabase to my repositories.

I have this line in one of my modules:

provide (isSingleton = true) { Room.databaseBuilder(androidApplication(), AppDatabase::class.java, Constants.DATABASE_NAME).build() }

When I run my app, I get this error:
java.lang.RuntimeException: cannot find implementation for br.com.evologica.biblio_android.data.database.AppDatabase. AppDatabase_Impl does not exist

Is there any way I can solve this problem?

Execute code on releaseContext

Hello,
I'm trying to use Koin with MVVM (android components) and Realm.

Realm forces a get an instance that has to be released to maintain the reference count.

I'm trying to figure out how to adquire koin in my scenario.

I have the following structure (simplified for the sake of the example)

class ArchersViewModel: ViewModel()
{

 val mDb: Realm

    val viewModelDao
    init {
        mDb = Realm.getDefaultInstance()
        viewModelDao = ArcherDao(mDb)
    }
    override fun onCleared() {
        mDb.close()
        super.onCleared()
    }
}

class ArcherDao(realm: Realm): RealmObjectDao<Archer>(realm, Archer::class.java)
{
  //methods to retrieve data
}


class ArchersFragment:Fragment()
{
lateinit var realmObjectListViewModel: ArchersViewModel
  override fun onActivityCreated(savedInstanceState: Bundle?) {
        super.onActivityCreated(savedInstanceState)
        realmObjectListViewModel = ViewModelProviders.of(this).get(ArchersViewModel::class.java)

}

So to start using koin I adapt the classes to use a koin module:

val archersModule = applicationContext {
   context("ArcherContext")
   {
       viewModel { ArchersViewModel(get())}
       bean { ArcherDao(get()) }
       provide { Realm.getDefaultInstance() as Realm}
   }
}

So I can modify the classes:

class ArchersViewModel(val viewModelDao: ArcherDao)
{
 ....
}
class ArcherDao(realm: Realm): RealmObjectDao<Archer>(realm, Archer::class.java)
{
  //methods to retrieve data
}
class ArchersFragment:Fragment()
{
    val realmObjectListViewModel by viewModel<ArchersViewModel>()

}

But now I have two doubts:

  1. Where I should release the context and
  2. How to force to close the realm instance when release the context

Any suggestion?

Thank in advance
Regards

Provide a Room DAO ?

i'm not sure how to provide a Room DAO, since it's an abstract class, any clues ?

Unable to run in old android versions

I have been using this great library for some time, however i always tested in devices with SDK greater than 21 now i had to run it in a device with SDK 17 and i'm getting the following errors:

E/dalvikvm: Could not find class 'org.koin.android.module.AndroidModule$androidApplication$2', referenced from method org.koin.android.module.AndroidModule.<init>

and this is the final exception

E/AndroidRuntime: FATAL EXCEPTION: main
                  java.lang.ExceptionInInitializerError
                      at com.innoware.aeromedicion.MainApplication.onCreate(MainApplication.kt:24)
                      at android.app.Instrumentation.callApplicationOnCreate(Instrumentation.java:1000)
                      at android.app.ActivityThread.handleBindApplication(ActivityThread.java:4391)
                      at android.app.ActivityThread.access$1300(ActivityThread.java:141)
                      at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1294)
                      at android.os.Handler.dispatchMessage(Handler.java:99)
                      at android.os.Looper.loop(Looper.java:137)
                      at android.app.ActivityThread.main(ActivityThread.java:5041)
                      at java.lang.reflect.Method.invokeNative(Native Method)
                      at java.lang.reflect.Method.invoke(Method.java:511)
                      at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
                      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)
                      at dalvik.system.NativeStart.main(Native Method)
                   Caused by: java.lang.NoClassDefFoundError: kotlin.jvm.internal.PropertyReference1Impl
                      at org.koin.android.module.AndroidModule.<clinit>(AndroidModule.kt)
                      at com.innoware.aeromedicion.MainApplication.onCreate(MainApplication.kt:24) 
                      at android.app.Instrumentation.callApplicationOnCreate(Instrumentation.java:1000) 
                      at android.app.ActivityThread.handleBindApplication(ActivityThread.java:4391) 
                      at android.app.ActivityThread.access$1300(ActivityThread.java:141) 
                      at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1294) 
                      at android.os.Handler.dispatchMessage(Handler.java:99) 
                      at android.os.Looper.loop(Looper.java:137) 
                      at android.app.ActivityThread.main(ActivityThread.java:5041) 
                      at java.lang.reflect.Method.invokeNative(Native Method) 
                      at java.lang.reflect.Method.invoke(Method.java:511) 
                      at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793) 
                      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560) 
                      at dalvik.system.NativeStart.main(Native Method) 

Assisted injection?

Hi! Nice library, really like it!
But I can't get how we can do so called assisted injection. Imagine I have MyPresenter(val someId: Int, val interactor: SomeInteractor), where someId is dynamic parameter that is known only by the time MyView (a Fragment) is created.

How I can provide the MyPresenter in this case?

How to use with custom view?

I can inject dependencies in activities and fragments, but can I inject in custom view?

class AppInputView : SearchView {
    private val router: Krouter by inject() // Unresolved reference: inject

    init {
        this.onQuerySubmit {
            context.toast(it)

            this.onActionViewCollapsed()
            this.clearFocus()
        }
    }

    constructor(context: Context) : super(context)
    constructor(context: Context, attrs: AttributeSet) : super(context, attrs)
    constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int) : super(context, attrs, defStyleAttr)
}

Can't get ViewModel in standard Fragment

Hey, really enjoying the library, much prefer it to the other options available. I've found however that you can't inject a ViewModel from the Android Architecture Components library into a standard Android Fragment (i.e. not the v4 support Fragment).

I've seen that it's because the extension methods extend the v4 support Fragment (the getViewModel method and the viewModel delegated property), and was wondering if there is any reason that it does't support standard fragments?

If not I'm happy to create a PR to add the necessary extension methods to the standard fragment if that helps.

Thanks,

Connor

Inject view in MVP architecture

Hello,

I have a problem with the implementation of MVP pattern using KOIN. I would like to inject view into presenter. My view is extending fragment and I do not know how to provide it to Presenter object while injection. I keep receiving info org.koin.error.BeanInstanceCreationException: Can't create bean Bean[class=com.pleez.fragment.sentlist.SentListContract.Presenter] due to error : org.koin.error.NoBeanDefFoundException: No bean definition found for class interface com.pleez.fragment.sentlist.SentListContract$View (Kotlin reflection is not available).

Here is how I have declared my module:

val sentListModule: Module = applicationContext {
    provide { SentListPresenter(get(), get()) as SentListContract.Presenter }
    provide { FragmentSentList() as SentListContract.View }
    provide { SentListDataSource(get(), get()) as SentListContract.DataSource }
}

here is how I declare presenter:

class SentListPresenter(val view: SentListContract.View ,val dataSource: SentListContract.DataSource): SentListContract.Presenter {

can someone tell me what is missing, or what I have done wrong?

Koin cannot instantiate bean with enum inside

Hi,

I am getting the following error:

Caused by: org.koin.error.BeanInstanceCreationException: Can't create bean Factory[class=com.myapp.ui.register.RegisterViewModel, binds~(android.arch.lifecycle.ViewModel)] due to error :
                  	java.lang.IllegalArgumentException: Invalid data. Unsupported type: com.myapp.data.User$Status (found in field status)

Useris a data class that has an enum of type Status

Any ideas what to do?

getViewModel() should use delegation to be consistent with inject()

The getViewModel() extension method should return a delegate as with inject(). I see two reasons for this:

  1. It makes the API more consistent (potentially a rename to injectViewModel() might help too)
  2. Currently it makes injecting the view model as a property impossible, this is because evaluation starts instantly (i.e. outside of the Android Lifecycle) when there may not be a context yet (e.g. a new Fragment instance that hasn't yet been attached).

Using delegation and lazy evaluation will allow the storage of the view model in a property as evaluation will not occur until the property is referenced.

Allow nullable dependencies?

Is it possible to provide an optional type?

I have application data that I'd like to inject, however the data isn't guaranteed at compile time and is fetched during runtime. Is it possible to inject a nullable type?

Currently I get the compile time error: inferred type User? is not a subtype of Any

Thanks in advance.

Not possible to add non-Android module to Android Koin

Hi there! Thanks for your hard work on Koin! Great library.
Anyway, I faced an issue, where you force to provide list of AndroidModule's to Application.startKoin(). Thus it is impossible to provide modules that are built, for example, in data or domain layers, which are usually written without platform dependencies.
Briefly looking through your code, I haven't found any serious reason to force AndroidModule for android artifact. What do you think? This will be a big win, if your android artifact's startKoin function will accept all descendants of Module.

Inject Activity

Hi,

Koin is awesome but I'm having an issue. Some libraries, like Firebase Analytics, depend on the current Activity to perform some actions like setting a current screen.

class Analytics(private val activity: Activity) {

  private val firebaseAnalytics: FirebaseAnalytics = FirebaseAnalytics.getInstance(activity)

  fun setCurrentScreen(screenName: String) {
    firebaseAnalytics.setCurrentScreen(activity, screenName, null)
  }
}
class MainPresenter(analytics: Analytics) { 
    
}
class MainActivity : AppCompatActivity() {

  val presenter : MainPresenter by inject()

}

Is this possible with Koin? If yes, then I don't see how.

Dynamic parameter injection

I'm using the koin-android-architecture version of the library. I've come across a situation where I'd like to use a parameter determined when an Activity/Fragment is created for a ViewModel. As an example:

SomeActivity.kt

class SomeActivity : BaseActivity() {

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

        val id = getIdExtra() // From intent
        TODO("use id")
        val viewModel = getViewModel<SomeViewModel>()
        // ...
    }
}

SomeViewModel.kt

class SomeViewModel(
    private val repository: Repository, // Singleton
    private val id: Long
) : BaseViewModel() {
// ...
}

Is there a good way of doing this? I know that Kodein has factory bindings, so I was wondering if there was something similar.

This issue is similar to #6 but I was wondering if there was a better method of achieving this now since that issue is relatively old.

App crashes with VerifyError on launch

Hi. First of all, nice work on Koin, it's such an awesome DI tool! I have a problem since upgrading from 0.8.0 to 0.8.2 with an Android app. The app crashes at startup with the following stack:

java.lang.VerifyError: Verifier rejected class org.koin.core.property.PropertyRegistry: void org.koin.core.property.PropertyRegistry.deleteAll(java.lang.String[]) failed to verify: void org.koin.core.property.PropertyRegistry.deleteAll(java.lang.String[]): [0x10] register v4 has type Reference: java.lang.Object but expected Precise Reference: java.lang.String (declaration of 'org.koin.core.property.PropertyRegistry' appears in /data/app/com.theantimony.antimony-1/split_lib_directories_apk.apk:classes2.dex)
at org.koin.Koin.(Koin.kt:21)
at org.koin.standalone.StandAloneContext.startKoin(StandAloneContext.kt:33)
at org.koin.standalone.StandAloneContext.startKoin$default(StandAloneContext.kt:24)
at org.koin.android.ext.android.AndroidExtKt.startKoin(AndroidExt.kt:27)
at org.koin.android.ext.android.AndroidExtKt.startKoin$default(AndroidExt.kt:25)
at com.theantimony.antimony.AntimonyApplication.onCreate(AntimonyApplication.kt:11)
at android.app.Instrumentation.callApplicationOnCreate(Instrumentation.java:1032)
at android.app.ActivityThread.handleBindApplication(ActivityThread.java:5970)
at android.app.ActivityThread.-wrap3(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1710)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6776)
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)

I have tried using Rebuild Project and deleting the build folder manually, and now the same thing happens after downgrading to 0.8.0 as well. Is this a knows issue? Thank you.

Missing ContextAwareActivity in Koin Android 0.8.0

Hello,

I am working through koin to understand how to use it on a future project and I am running into an issue where I dont have the ContextAwareActivity. I see it referenced in the docs. Was this removed? If so how do I make an Activity aware of my context

Thanks!

Forwarding parameters

Koin 0.9.0 is really great
Thanks for the parameter support when injecting dependencies. It is working great.

I have a small optimization for injecting with parameters.
It would be fantastic if we can forward this parameter map.

e.g.

class MyActivity : Activity() {
   val presenter: MyPresenter by inject(parameters = mapOf("activity" to this)
}

class MyPresenter(navigator: Navigator) {

}

class Navigator(activity: Activity) {

}

and the module looks like this

val myModule: Module = applicationContext {
   context("Screen") {
      bean { params -> MyPresenter(get()) }  // here we have the params with the activity 
      bean { params -> Navigator(params["activity"]) }  // BUT the activity is needed here (and here are params null)
   }
}

can you provide us with the possibillty to forward these params in the get() method, e.g

val myModule: Module = applicationContext {
   context("Screen") {
      bean { params -> MyPresenter(get(params)) }  // forward params in get(params)
      bean { params -> Navigator(params["activity"]) }  // so we can access the params here
   }
}

looking at the get() functions it should be possible
in the current version 0.9.0 you pass an emptyMap to the resolve functions.

inline fun <reified T : Any> get(): T = koinContext.resolveByClass(emptyMap())
inline fun <reified T : Any> get(name: String): T = koinContext.resolveByName(name, emptyMap())

maybe we can do something like this:

inline fun <reified T : Any> get(parameters: ParameterMap = emptyMap()): T = koinContext.resolveByClass(parameters)
inline fun <reified T : Any> get(name: String, parameters: ParameterMap = emptyMap()): T = koinContext.resolveByName(name, parameters)

What do you think about this?

Error:Failed to resolve: org.koin:koin-android-architecture:0.8.0

Hi, I updated my project to koin 0.8.0 in order to try the new koin-android-architecture module but gradle can't resolve it.

Error:Failed to resolve: org.koin:koin-android-architecture:0.8.0

My gradle file:

implementation "org.koin:koin-android-architecture:$koin_version"

It seems koin-android-architecture isn't available in jcenter

[Feature proposal] Android intent arguments

Hello dear Koin users,

I was talking to people using Koin, about setProperty to help set a Koin property in your app. But an overuse of this feature can lead to putting all your arguments data between activities/fragments in Koin properties, whereas we should respect the Android approach: keep argument data in intents.

I would like to give some "Android extra" help on intent, to help set up arguments on Android and avoid misuse with Koin properties.

I propose a startActivity and withArguments :

startActivity<WeatherDetailActivity> {
            withArguments(
                    PROPERTY_WEATHER_DATE to date,
                    PROPERTY_ADDRESS to address,
                    PROPERTY_WEATHER_ITEM_ID to id)
        }

and on receiving activity or fragment, argument binding:

class WeatherDetailActivity : AppCompatActivity() {

    // Get all needed data
    val address by argument<String>(PROPERTY_ADDRESS)
    val now by argument<Date>(PROPERTY_WEATHER_DATE)
    val id by argument<String>(PROPERTY_WEATHER_ITEM_ID)

This will bind those properties with the underlying intent. This feature is sort of borderline with Koin goals, but I think we are still in "assembling" components subject.

Source: https://github.com/Ekito/koin/blob/0.9.0/android/koin-android/src/main/java/org/koin/android/ext/android/Extras.kt

Sample app with intent arguments: https://github.com/Ekito/koin-samples/blob/master/samples/android-weatherapp-mvvm/

Feature available in Koin 0.9.0-alpha-5.

--

Just put some 👍, other emojis or comments :)

Thanks for your feedback.

Context.getKoin() is not always convenient.

Hi!
I have the case when I need to get dependency from the Koin and provide it to the factory method (abstract in super class). And at the moment this method called there is no context in Conductor's Controller yet.
So I was forced to call StandAloneContext.koinContext.get().

Maybe it will be better to have getKoin() from everywhere if it is just an object (StandAloneContext)?

Can't use injected dependencies

Hi, i'm new with Koin, and i configured all the stuff but when i tried to use the modules this error came out:

   FATAL EXCEPTION: main
   Process: com.app.careyes, PID: 11583
   java.lang.RuntimeException: java.lang.reflect.InvocationTargetException  
   at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:448)
   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)
                                                              Caused by: java.lang.reflect.InvocationTargetException
                                                                 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: org.koin.error.BeanInstanceCreationException: Can't create bean Bean[name='',class=com.app.careyes.modules.historico.HistoricoPresenter,singleton=true,binds~(com.app.careyes.mvp.contracts.HistoricoContract.Presenter)] due to error : org.koin.error.BeanInstanceCreationException: Can't create bean Bean[name='',class=com.app.careyes.modules.historico.HistoricoInteractor,singleton=true,binds~(com.app.careyes.mvp.contracts.HistoricoContract.Interactor)] due to error : org.koin.error.DependencyResolutionException: Cyclic dependency for class com.app.careyes.mvp.contracts.HistoricoContract$Presenter
                                                                 at org.koin.core.instance.InstanceFactory.createInstance(InstanceFactory.kt:68)
                                                                 at org.koin.core.instance.InstanceFactory.retrieveInstance(InstanceFactory.kt:32)
                                                                 at org.koin.KoinContext.resolveInstance(KoinContext.kt:58)
                                                                 at com.app.careyes.modules.historico.HistoricoFragment$$special$$inlined$inject$1.invoke(AndroidExt.kt:94)
                                                                 at kotlin.SynchronizedLazyImpl.getValue(Lazy.kt:130)
                                                                 at com.app.careyes.modules.historico.HistoricoFragment.getPresenter(HistoricoFragment.kt:0)
                                                                 at com.app.careyes.modules.historico.HistoricoFragment$onViewCreated$$inlined$apply$lambda$1.run(HistoricoFragment.kt:51)
                                                                 at android.os.Handler.handleCallback(Handler.java:790)
                                                                 at android.os.Handler.dispatchMessage(Handler.java:99)
                                                                 at android.os.Looper.loop(Looper.java:164)
                                                                 at android.app.ActivityThread.main(ActivityThread.java:6494)
                                                                 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) 

And this is my AppModule:

class AppModule : AndroidModule() {
override fun context() = applicationContext {

    context(name = Context.Menu){
        provide { AgendaFragment() }
        provide { MenuFragment() }
        provide { SobreFragment() }
    }

    context(name = Context.Auth) {
        provide { LoginFragment() } bind AuthContract.View::class
        provide { AuthInteractor(get(), get(), get()) } bind AuthContract.Interactor::class
        provide { AuthPresenter(get(), get()) } bind AuthContract.Presenter::class
    }

    context(name = Context.Pacients) {
        provide { PacientsFragment() } bind PacientsContract.View::class
        provide { PacientsPresenter(get(), get()) } bind PacientsContract.Presenter::class
        provide { PacientsInteractor(get(), get(), get()) } bind PacientsContract.Interactor::class
    }

    context(name = Context.Avisos) {
        provide { AvisosFragment() } bind AvisosContract.View::class
        provide { AvisosPresenter(get(), get()) } bind AvisosContract.Presenter::class
        provide { AvisosInteractor(get(), get(), get()) } bind AvisosContract.Interactor::class
    }

    context(name = Context.Historico) {
        provide { HistoricoFragment() } bind HistoricoContract.View::class
        provide { HistoricoPresenter(get(), get()) } bind HistoricoContract.Presenter::class
        provide { HistoricoInteractor(get(), get(), get()) } bind HistoricoContract.Interactor::class
    }

    context(name = Context.Evolucao) {
        provide { EvolucaoFragment() } bind EvolucaoContract.View::class
        provide { EvolucaoInteractor(get(), get(), get()) } bind EvolucaoContract.Interactor::class
        provide { EvolucaoPresenter(get(), get()) } bind EvolucaoContract.Presenter::class
    }

    context(name = Context.NotaEvolucao){
        provide { NotaEvolucaoFragment() } bind NotaEvolucaoContract.View::class
        provide { NotaEvolucaoInteractor(get(),get(),get()) } bind NotaEvolucaoContract.Interactor::class
        provide { NotaEvolucaoPresenter(get(), get()) } bind NotaEvolucaoContract.Presenter::class
    }

    provide { client() }
    provide { sharedPreferences() }
    provide { retrofit(get(), "") }
    provide { careYesApi(get()) }
}

private fun careYesApi(retrofit: Retrofit): CareYesApi {
    return retrofit.create(CareYesApi::class.java)
}

private fun retrofit(okHttpClient: OkHttpClient, base_url: String): Retrofit {
    return Retrofit.Builder()
            .baseUrl(base_url)
            .addConverterFactory(MoshiConverterFactory.create())
            .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
            .client(okHttpClient)
            .build()
}

private fun client(): OkHttpClient {
    return OkHttpClient.Builder()
            .connectTimeout(30, TimeUnit.SECONDS)
            .readTimeout(30, TimeUnit.SECONDS)
            .build()
}

private fun sharedPreferences(): SharedPreferences {
    return androidApplication.getSharedPreferences("User", android.content.Context.MODE_PRIVATE)
}

/**
 * Constantes usadas para definir os escopos das dependências
 */
object Context {
    val Auth = "Auth"
    val Pacients = "Pacients"
    val Avisos = "Avisos"
    val Historico = "Historico"
    val Evolucao = "Evolucao"
    val Menu = "Menu"
    val NotaEvolucao = "NotaEvolucao"
}
}

what am i missing? Thank you for the attention.

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.