Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/kotlin/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android 如果没有@Inject构造函数或@Provides注释方法,则无法提供ViewModel_Android_Kotlin_Dagger 2 - Fatal编程技术网

Android 如果没有@Inject构造函数或@Provides注释方法,则无法提供ViewModel

Android 如果没有@Inject构造函数或@Provides注释方法,则无法提供ViewModel,android,kotlin,dagger-2,Android,Kotlin,Dagger 2,我正在尝试在两个活动之间共享一个ViewModel。我发现以下错误如果没有@Inject构造函数或@Provides注释方法,就无法提供ViewModel。我试图实现的主要目标是在不同的活动之间建立一个共享的ViewModel,在我的例子中是LoginActivity和SampleActivity。最好的方法是使用ViewModelFactory。因此,我使用dagger将ViewModelFactory注入到这两个活动中,目前我仍停留在上述错误上 以下是build.gadle文件: imple

我正在尝试在两个活动之间共享一个ViewModel。我发现以下错误
如果没有@Inject构造函数或@Provides注释方法,就无法提供ViewModel
。我试图实现的主要目标是在不同的活动之间建立一个共享的ViewModel,在我的例子中是
LoginActivity
SampleActivity
。最好的方法是使用ViewModelFactory。因此,我使用dagger将ViewModelFactory注入到这两个活动中,目前我仍停留在上述错误上

以下是
build.gadle
文件:

implementation("com.google.dagger:dagger:2.26")
implementation("com.google.dagger:dagger-android-support:2.26")
implementation("com.google.dagger:dagger-android:2.26")
kapt "com.google.dagger:dagger-android-processor:2.26"
kapt "com.google.dagger:dagger-compiler:2.26"
这里是ActivityModule.kt:

@Module
abstract class ActivityModule {

    @ContributesAndroidInjector
    abstract fun contributeLoginActivity(): LoginActivity

    @ContributesAndroidInjector
    abstract fun contributeSampleActivity(): SampleActivity
}
@Singleton
@Component(
    modules = [
        AppModule::class,
        AndroidInjectionModule::class,
        ViewModelModule::class,
        ActivityModule::class
    ]
)
interface AppComponent {
    fun inject(app: MainApplication)

    @Component.Factory
    interface Factory {
        fun create(@BindsInstance context: Context): AppComponent
    }
}
@Suppress("DEPRECATED_JAVA_ANNOTATION")
@Documented
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@MapKey
internal annotation class ViewModelKey(val value: KClass<out ViewModel>)
@Module
abstract class ViewModelModule {

    @Binds
    @IntoMap
    @ViewModelKey(MainViewModel::class) // PROVIDE YOUR OWN MODELS HERE
    internal abstract fun bindMainViewModel(mainViewModel: MainViewModel): ViewModel


    @Binds
    internal abstract fun bindViewModelProviderFactory(factory: ViewModelProviderFactory): ViewModelProvider.Factory
}
这里是AppComponent.kt:

@Module
abstract class ActivityModule {

    @ContributesAndroidInjector
    abstract fun contributeLoginActivity(): LoginActivity

    @ContributesAndroidInjector
    abstract fun contributeSampleActivity(): SampleActivity
}
@Singleton
@Component(
    modules = [
        AppModule::class,
        AndroidInjectionModule::class,
        ViewModelModule::class,
        ActivityModule::class
    ]
)
interface AppComponent {
    fun inject(app: MainApplication)

    @Component.Factory
    interface Factory {
        fun create(@BindsInstance context: Context): AppComponent
    }
}
@Suppress("DEPRECATED_JAVA_ANNOTATION")
@Documented
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@MapKey
internal annotation class ViewModelKey(val value: KClass<out ViewModel>)
@Module
abstract class ViewModelModule {

    @Binds
    @IntoMap
    @ViewModelKey(MainViewModel::class) // PROVIDE YOUR OWN MODELS HERE
    internal abstract fun bindMainViewModel(mainViewModel: MainViewModel): ViewModel


    @Binds
    internal abstract fun bindViewModelProviderFactory(factory: ViewModelProviderFactory): ViewModelProvider.Factory
}
这里是AppModule.kt

@Module(includes = [ViewModelModule::class])
class AppModule {

}
class MainApplication: Application(), HasAndroidInjector {

    @Inject
    lateinit var dispatchingAndroidInjector: DispatchingAndroidInjector<Any>

    override fun onCreate() {
        super.onCreate()

        DaggerAppComponent.factory().create(this).inject(this)


    }


    override fun androidInjector() = dispatchingAndroidInjector

}
class LoginActivity : DaggerAppCompatActivity() {

    @Inject lateinit var modelFactory: ViewModelProvider.Factory
    lateinit var viewModel: MainViewModel

    override fun onCreate(savedInstanceState: Bundle?) {
        AndroidInjection.inject(this)
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_login)
        val button: Button = findViewById(R.id.button)
        button.setOnClickListener { onButtonClick() }
        val label: TextView = findViewById(R.id.counter)

        viewModel =  ViewModelProvider(this, modelFactory).get(MainViewModel::class.java)
        println("stack: ${viewModel.hashCode()}")

        viewModel.userLogin.observe(this, Observer{ user ->
            print("Debug: ${user}")
            if(user != null){
                label.text = user.user.name
                redirectToLogin()
            }
        })
    }


    fun onButtonClick(){
        var username: EditText = findViewById(R.id.username)
        var password: EditText = findViewById(R.id.password)
        println(username.text.toString())
        println(password.text.toString())
        viewModel.setUser(username.text.toString(), password.text.toString())
    }

    fun redirectToLogin(){
        println("Login done!")
        val intent = Intent(this, SampleActivity::class.java)
        intent.putExtra("extra", viewModel.userLogin.value)
        startActivity(intent)
    }

}
class SampleActivity : DaggerAppCompatActivity() {

    lateinit var viewModel: MainViewModel
    @Inject lateinit var modelFactory: ViewModelProvider.Factory

    override fun onCreate(savedInstanceState: Bundle?) {
        AndroidInjection.inject(this)
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_sample)
        val loggedInUser: LoggedInUser? = intent.getParcelableExtra("extra")
//        println("extra: $loggedInUser")
        viewModel = ViewModelProvider(this, modelFactory).get(MainViewModel::class.java)
        println("stack: ${viewModel.hashCode()}")
        println(" $ WORKS: ${viewModel.userLogin.value?.user?.name}")


    }
}
ViewModelKey.kt

@Module
abstract class ActivityModule {

    @ContributesAndroidInjector
    abstract fun contributeLoginActivity(): LoginActivity

    @ContributesAndroidInjector
    abstract fun contributeSampleActivity(): SampleActivity
}
@Singleton
@Component(
    modules = [
        AppModule::class,
        AndroidInjectionModule::class,
        ViewModelModule::class,
        ActivityModule::class
    ]
)
interface AppComponent {
    fun inject(app: MainApplication)

    @Component.Factory
    interface Factory {
        fun create(@BindsInstance context: Context): AppComponent
    }
}
@Suppress("DEPRECATED_JAVA_ANNOTATION")
@Documented
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@MapKey
internal annotation class ViewModelKey(val value: KClass<out ViewModel>)
@Module
abstract class ViewModelModule {

    @Binds
    @IntoMap
    @ViewModelKey(MainViewModel::class) // PROVIDE YOUR OWN MODELS HERE
    internal abstract fun bindMainViewModel(mainViewModel: MainViewModel): ViewModel


    @Binds
    internal abstract fun bindViewModelProviderFactory(factory: ViewModelProviderFactory): ViewModelProvider.Factory
}
这里是
MainApplication.kt

@Module(includes = [ViewModelModule::class])
class AppModule {

}
class MainApplication: Application(), HasAndroidInjector {

    @Inject
    lateinit var dispatchingAndroidInjector: DispatchingAndroidInjector<Any>

    override fun onCreate() {
        super.onCreate()

        DaggerAppComponent.factory().create(this).inject(this)


    }


    override fun androidInjector() = dispatchingAndroidInjector

}
class LoginActivity : DaggerAppCompatActivity() {

    @Inject lateinit var modelFactory: ViewModelProvider.Factory
    lateinit var viewModel: MainViewModel

    override fun onCreate(savedInstanceState: Bundle?) {
        AndroidInjection.inject(this)
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_login)
        val button: Button = findViewById(R.id.button)
        button.setOnClickListener { onButtonClick() }
        val label: TextView = findViewById(R.id.counter)

        viewModel =  ViewModelProvider(this, modelFactory).get(MainViewModel::class.java)
        println("stack: ${viewModel.hashCode()}")

        viewModel.userLogin.observe(this, Observer{ user ->
            print("Debug: ${user}")
            if(user != null){
                label.text = user.user.name
                redirectToLogin()
            }
        })
    }


    fun onButtonClick(){
        var username: EditText = findViewById(R.id.username)
        var password: EditText = findViewById(R.id.password)
        println(username.text.toString())
        println(password.text.toString())
        viewModel.setUser(username.text.toString(), password.text.toString())
    }

    fun redirectToLogin(){
        println("Login done!")
        val intent = Intent(this, SampleActivity::class.java)
        intent.putExtra("extra", viewModel.userLogin.value)
        startActivity(intent)
    }

}
class SampleActivity : DaggerAppCompatActivity() {

    lateinit var viewModel: MainViewModel
    @Inject lateinit var modelFactory: ViewModelProvider.Factory

    override fun onCreate(savedInstanceState: Bundle?) {
        AndroidInjection.inject(this)
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_sample)
        val loggedInUser: LoggedInUser? = intent.getParcelableExtra("extra")
//        println("extra: $loggedInUser")
        viewModel = ViewModelProvider(this, modelFactory).get(MainViewModel::class.java)
        println("stack: ${viewModel.hashCode()}")
        println(" $ WORKS: ${viewModel.userLogin.value?.user?.name}")


    }
}
SampleActivity.kt

@Module(includes = [ViewModelModule::class])
class AppModule {

}
class MainApplication: Application(), HasAndroidInjector {

    @Inject
    lateinit var dispatchingAndroidInjector: DispatchingAndroidInjector<Any>

    override fun onCreate() {
        super.onCreate()

        DaggerAppComponent.factory().create(this).inject(this)


    }


    override fun androidInjector() = dispatchingAndroidInjector

}
class LoginActivity : DaggerAppCompatActivity() {

    @Inject lateinit var modelFactory: ViewModelProvider.Factory
    lateinit var viewModel: MainViewModel

    override fun onCreate(savedInstanceState: Bundle?) {
        AndroidInjection.inject(this)
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_login)
        val button: Button = findViewById(R.id.button)
        button.setOnClickListener { onButtonClick() }
        val label: TextView = findViewById(R.id.counter)

        viewModel =  ViewModelProvider(this, modelFactory).get(MainViewModel::class.java)
        println("stack: ${viewModel.hashCode()}")

        viewModel.userLogin.observe(this, Observer{ user ->
            print("Debug: ${user}")
            if(user != null){
                label.text = user.user.name
                redirectToLogin()
            }
        })
    }


    fun onButtonClick(){
        var username: EditText = findViewById(R.id.username)
        var password: EditText = findViewById(R.id.password)
        println(username.text.toString())
        println(password.text.toString())
        viewModel.setUser(username.text.toString(), password.text.toString())
    }

    fun redirectToLogin(){
        println("Login done!")
        val intent = Intent(this, SampleActivity::class.java)
        intent.putExtra("extra", viewModel.userLogin.value)
        startActivity(intent)
    }

}
class SampleActivity : DaggerAppCompatActivity() {

    lateinit var viewModel: MainViewModel
    @Inject lateinit var modelFactory: ViewModelProvider.Factory

    override fun onCreate(savedInstanceState: Bundle?) {
        AndroidInjection.inject(this)
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_sample)
        val loggedInUser: LoggedInUser? = intent.getParcelableExtra("extra")
//        println("extra: $loggedInUser")
        viewModel = ViewModelProvider(this, modelFactory).get(MainViewModel::class.java)
        println("stack: ${viewModel.hashCode()}")
        println(" $ WORKS: ${viewModel.userLogin.value?.user?.name}")


    }
}
我似乎找不到问题所在,以下是整个错误堆栈:

public abstract interface AppComponent {
                ^
      company.MyApp.ViewModels.MainViewModel is injected at
          company.MyApp.di.ViewModelModule.bindMainViewModel$app_debug(mainViewModel)
      java.util.Map<java.lang.Class<? extends androidx.lifecycle.ViewModel>,javax.inject.Provider<androidx.lifecycle.ViewModel>> is injected at
          company.MyApp.ViewModels.ViewModelProviderFactory(creators)
      company.MyApp.ViewModels.ViewModelProviderFactory is injected at
          company.MyApp.di.ViewModelModule.bindViewModelProviderFactory$app_debug(factory)
      androidx.lifecycle.ViewModelProvider.Factory is injected at
          company.MyApp.LoginActivity.modelFactory
      company.MyApp.LoginActivity is injected at
          dagger.android.AndroidInjector.inject(T) [company.MyApp.di.AppComponent → company.MyApp.di.ActivityModule_ContributeLoginActivity.LoginActivitySubcomponent]
  The following other entry points also depend on it:
      dagger.android.AndroidInjector.inject(T) [company.MyApp.di.AppComponent → company.MyApp.di.ActivityModule_ContributeSampleActivity.SampleActivitySubcomponent]
公共抽象接口AppComponent{
^
company.MyApp.ViewModels.MainViewModel在
company.MyApp.di.ViewModelModule.bindMainViewModel$app\u调试(mainViewModel)

java.util.Map您的
MainViewModel
是否有
@Inject
构造函数?我的MainViewModel中没有@Inject构造函数。考虑到我没有要传递到构造函数的任何内容,我是否需要一个构造函数?