Code Monkey home page Code Monkey logo

Comments (27)

arnaudgiuliani avatar arnaudgiuliani commented on May 14, 2024 6

Yes Ok. Sorry there was a mistake in my answer.
You need to write:

val model: T by viewModel(T::class) or val model: T by lazy {getViewModel(T::class)}

Let me write a patch 👍

from koin.

ductranit avatar ductranit commented on May 14, 2024 4

@arnaudgiuliani
Are there any elegant approach that not pass class as a parameter to the activity?

Hope this isn't too late. You can try this:


open class BaseFragment<M : ViewModel> : Fragment() {
    val viewModel: M by lazy { getViewModel(viewModelClass()) }

    @Suppress("UNCHECKED_CAST")
    private fun viewModelClass(): KClass<M> {
        // dirty hack to get generic type https://stackoverflow.com/a/1901275/719212
        return ((javaClass.genericSuperclass as ParameterizedType)
            .actualTypeArguments[0] as Class<M>).kotlin
    }
}

from koin.

rasoulmiri avatar rasoulmiri commented on May 14, 2024 4

@nEdAy if use ViewDataBinding use need change 0 to 1
because ViewModel is 2 in paramaeters

open class BaseFragment<B : ViewDataBinding, M : ViewModel> : Fragment() {
    val viewModel: M by lazy { getViewModel(viewModelClass()) }

    @Suppress("UNCHECKED_CAST")
    private fun viewModelClass(): KClass<M> {
        // dirty hack to get generic type https://stackoverflow.com/a/1901275/719212
        return ((javaClass.genericSuperclass as ParameterizedType)
            .actualTypeArguments[1] as Class<M>).kotlin
    }
}

from koin.

silviorp avatar silviorp commented on May 14, 2024 3

@fathallah92
No. I've used the following approach:

  • I have a BaseActivity:
open class BaseActivity<out ViewModelType : BaseViewModel>(clazz: KClass<ViewModelType>) :
        AppCompatActivity() {

    val viewModel: ViewModelType by viewModel(clazz)
}
  • And on each activity, I pass the viewModel class like this:
class MainActivity : BaseActivity<MainViewModel>(MainViewModel::class) {}

But I'm not coding on this project for some time (it's in production, though), so, probably there are better ways to do it.

from koin.

arnaudgiuliani avatar arnaudgiuliani commented on May 14, 2024 2

API has been updated to have val model: T by viewModel(<KClass<T>>) and avoid reified types this way.

Your base activity must be like:

class Base Activity<T : ViewModel>(clazz : KClass<T>){
    val model : T by viewModel(clazz)
}

We can't pass reified parameters from class.

from koin.

nEdAy avatar nEdAy commented on May 14, 2024 2

@arnaudgiuliani
Are there any elegant approach that not pass class as a parameter to the activity?

Hope this isn't too late. You can try this:


open class BaseFragment<M : ViewModel> : Fragment() {
    val viewModel: M by lazy { getViewModel(viewModelClass()) }

    @Suppress("UNCHECKED_CAST")
    private fun viewModelClass(): KClass<M> {
        // dirty hack to get generic type https://stackoverflow.com/a/1901275/719212
        return ((javaClass.genericSuperclass as ParameterizedType)
            .actualTypeArguments[0] as Class<M>).kotlin
    }
}

There is a problem when using databinding at the same time.

from koin.

fredy-mederos avatar fredy-mederos commented on May 14, 2024 1

Your code looks good to me.
Are you shure you are compiling koin-android-architecture 0.8.2 ??

// Koin for Android Architecture Components
compile "org.koin:koin-android-architecture:0.8.2"

from koin.

silviorp avatar silviorp commented on May 14, 2024 1

The problem was the version I was using, 0.8.0. But now that I was able to import, there's another problem:

screen shot 2018-02-16 at 21 56 32

Do you guys know how should I proceed? I really like to get the viewModel instance inside my BaseActivity to handle snackbar, toast and other generic observers from my ViewModel.

from koin.

silviorp avatar silviorp commented on May 14, 2024 1

What I trying to do is receive the type of View Model as parameter and inject a new instance of this type. There's no MyViewModel. The ViewModel types would be received in a generic way. The problem is because it's an inline function with reified type, it's not allowed to receive the type like we have here. It would be amazing to be able to use like this: val myViewModel : T by viewModel(T::class) or val myViewModel: T by viewModel()

I'm going to try to strip the injection source code and implement a ViewModelFactory to initialize it inside the BaseActivity but this would not benefit from the rest of the library features

from koin.

caleb-allen avatar caleb-allen commented on May 14, 2024

Are you importing correctly?

import org.koin.android.architecture.ext.viewModel

from koin.

caleb-allen avatar caleb-allen commented on May 14, 2024

Maybe try declaring the type in the value?

val myViewModel : MyViewModel by viewModel()

from koin.

caleb-allen avatar caleb-allen commented on May 14, 2024

You don't need the angle brackets for the viewmodel I believe

from koin.

caleb-allen avatar caleb-allen commented on May 14, 2024

Scratch that I misunderstood that your activity was generic

from koin.

caleb-allen avatar caleb-allen commented on May 14, 2024

What about

val myViewModel : MyViewModel<T> by viewModel()

from koin.

arnaudgiuliani avatar arnaudgiuliani commented on May 14, 2024

Hello,

we can't use generic type T with infered Kotlin parameter :/

Best thing is to add a method to allow such declaration: val myViewModel : MyViewModel<T> by viewModel(T::class) or something like that.

from koin.

silviorp avatar silviorp commented on May 14, 2024

After 2 days I had no success trying to make this work.
I'm having a hard time working with generics in kotlin, something I could do in Java very easily.
I don't want to try another libraries for dependency injection but since I'm in the beginning of a new project in the company I work for, if I can't solve this quickly I'll be forced to try another libs or maybe, write this in Java.

from koin.

caleb-allen avatar caleb-allen commented on May 14, 2024

Does

 val myViewModel : T by viewModel()

Not work?

from koin.

arnaudgiuliani avatar arnaudgiuliani commented on May 14, 2024

fix is available in current alpha: 0.9.0-alpha-11

from koin.

silviorp avatar silviorp commented on May 14, 2024

It worked! Thanks very much!!! I'll try make an extension or something like that to avoid having to pass the class as a parameter but for now, that's working wonderfully!!

from koin.

arnaudgiuliani avatar arnaudgiuliani commented on May 14, 2024

Cool :) I close the issue.

from koin.

jakoss avatar jakoss commented on May 14, 2024

@shrpereira Did you manage to avoid having to pass the class as a parameter?

from koin.

arnaudgiuliani avatar arnaudgiuliani commented on May 14, 2024

@shrpereira You will be able to get viewModel by class with viewModelByClass() and getViewModelByClass. This is the final version of the API fir release 0.9.0

from koin.

fathallah92 avatar fathallah92 commented on May 14, 2024

@shrpereira Have you added an extension to not pass class as a parameter to the activity ?

from koin.

loalexzzzz avatar loalexzzzz commented on May 14, 2024

@arnaudgiuliani
Are there any elegant approach that not pass class as a parameter to the activity?

from koin.

Adamshick012 avatar Adamshick012 commented on May 14, 2024

Is there an example of how this is implemented on a example Fragment? I am getting a No definition found error when I use the above example. The only way I have gotten it to work was going around the lazy and doing a loadKoinModules(module{single{ExampleViewModel()}}) inside the ExampleFragment which kind of defeats the purpose.

from koin.

loalexzzzz avatar loalexzzzz commented on May 14, 2024

@arnaudgiuliani
Are there any elegant approach that not pass class as a parameter to the activity?

Hope this isn't too late. You can try this:


open class BaseFragment<M : ViewModel> : Fragment() {
    val viewModel: M by lazy { getViewModel(viewModelClass()) }

    @Suppress("UNCHECKED_CAST")
    private fun viewModelClass(): KClass<M> {
        // dirty hack to get generic type https://stackoverflow.com/a/1901275/719212
        return ((javaClass.genericSuperclass as ParameterizedType)
            .actualTypeArguments[0] as Class<M>).kotlin
    }
}

I have figured out by myself, quite similar with your approach , thank you for answer, happy coding :D

from koin.

tomek27 avatar tomek27 commented on May 14, 2024

I did it like this

abstract class BaseFragment<VM: BaseViewModel> : Fragment() {

    val viewModel: VM by lazy { getViewModel(clazz) }

    abstract var clazz: KClass<VM>

}

from koin.

Related Issues (20)

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.