kotlin + dagger 2:任务执行失败':app:kaptDebugKotlin'

时间:2018-02-21 09:32:27

标签: java android kotlin

所以,我试图创建一个例子,从GithubBrowserSample和Kotlin一起鼓舞人心。我已成功迁移到kotlin代码但我的ApplicationComponent.kt收到错误。

Error:(12, 2) error: [dagger.android.AndroidInjector.inject(T)] java.util.Map<java.lang.Class<? extends android.support.v4.app.Fragment>,javax.inject.Provider<dagger.android.AndroidInjector.Factory<? extends android.support.v4.app.Fragment>>> cannot be provided without an @Provides-annotated method.
public abstract interface ApplicationComponent {
                ^
      java.util.Map<java.lang.Class<? extends android.support.v4.app.Fragment>,javax.inject.Provider<dagger.android.AndroidInjector.Factory<? extends android.support.v4.app.Fragment>>> is injected at
          dagger.android.DispatchingAndroidInjector.<init>(injectorFactories)
      dagger.android.DispatchingAndroidInjector<android.support.v4.app.Fragment> is injected at
          com.chintansoni.android.architecturecomponentsblueprint.base.BaseActivity.dispatchingAndroidInjector
      com.chintansoni.android.architecturecomponentsblueprint.view.activity.SplashActivity is injected at
          dagger.android.AndroidInjector.inject(arg0)

我可以看到问题来自import dagger.android.AndroidInjectionModule

的AndroidInjectionModule

让我分享一下我的代码片段。

KotlinApplication.kt

class KotlinApplication : Application(), HasActivityInjector {

    @Inject
    lateinit var dispatchingAndroidInjector: DispatchingAndroidInjector<Activity>

    override fun onCreate() {
        super.onCreate()
        initializeLogger()
        initializeAppInjector()
    }

    private fun initializeAppInjector() {
        AppInjector.init(this)
    }

    private fun initializeLogger() {
        if (BuildConfig.DEBUG) {
            Timber.plant(Timber.DebugTree())
        }
    }

    override fun activityInjector(): DispatchingAndroidInjector<Activity>? {
        return dispatchingAndroidInjector
    }
}

AppInjector.kt

object AppInjector {
    fun init(kotlinApplication: KotlinApplication) {
        DaggerApplicationComponent.builder()
                .application(kotlinApplication)
                .build()
                .inject(kotlinApplication)

        kotlinApplication.registerActivityLifecycleCallbacks(object : Application.ActivityLifecycleCallbacks {

            override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) {
                handleActivity(activity)
            }

            override fun onActivityStarted(activity: Activity) {

            }

            override fun onActivityResumed(activity: Activity) {

            }

            override fun onActivityPaused(activity: Activity) {

            }

            override fun onActivityStopped(activity: Activity) {

            }

            override fun onActivitySaveInstanceState(activity: Activity, outState: Bundle) {

            }

            override fun onActivityDestroyed(activity: Activity) {

            }
        })
    }

    private fun handleActivity(activity: Activity) {
        if (activity is HasSupportFragmentInjector) {
            AndroidInjection.inject(activity)
        }
        (activity as? FragmentActivity)?.supportFragmentManager?.registerFragmentLifecycleCallbacks(
                object : FragmentManager.FragmentLifecycleCallbacks() {
                    override fun onFragmentCreated(fm: FragmentManager, f: Fragment,
                                                   savedInstanceState: Bundle) {
                        if (f is Injectable) {
                            AndroidSupportInjection.inject(f)
                        }
                    }
                }, true)
    }
}

ApplicationComponent.kt

@Singleton
@Component(modules = [(AndroidInjectionModule::class), (AppModule::class), (SplashActivityModule::class)])
interface ApplicationComponent {

    @Component.Builder
    interface Builder {

        @BindsInstance
        fun application(application: Application): Builder

        fun build(): ApplicationComponent
    }

    fun inject(kotlinApplication: KotlinApplication)
}

SplashActivityModule.kt

@Module
abstract class SplashActivityModule {
    @ContributesAndroidInjector(modules = [(FragmentBuildersModule::class)])
    internal abstract fun contributeSplashActivity(): SplashActivity
}

BaseActivity.kt

abstract class BaseActivity : AppCompatActivity(), HasSupportFragmentInjector {

    @Inject
    lateinit var dispatchingAndroidInjector: DispatchingAndroidInjector<Fragment>

    override fun supportFragmentInjector(): DispatchingAndroidInjector<Fragment> {
        return dispatchingAndroidInjector
    }

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

    abstract fun getLayoutResource(): Int
}

我的SplashActivity延长了BaseActivity

2 个答案:

答案 0 :(得分:1)

如果您使用支持库中的Fragment,则必须使用HasSupportFragmentInjector中的KotlinApplication

class KotlinApplication : Application(), HasActivityInjector, HasSupportFragmentInjector {

    @Inject
    lateinit var dispatchingAndroidInjector: DispatchingAndroidInjector<Activity>

    @Inject
    lateinit var dispatchingFragmentInjector: DispatchingAndroidInjector<Fragment>

    override fun onCreate() {
        super.onCreate()
        initializeLogger()
        initializeAppInjector()
    }

    private fun initializeAppInjector() {
        AppInjector.init(this)
    }

    private fun initializeLogger() {
        if (BuildConfig.DEBUG) {
            Timber.plant(Timber.DebugTree())
        }
    }

    override fun activityInjector(): DispatchingAndroidInjector<Activity>? {
        return dispatchingAndroidInjector
    }

    override fun supportFragmentInjector(): AndroidInjector<Fragment>? {
        return dispatchingFragmentInjector
    }
}

您还需要在AndroidSupportInjectionModule中安装AndroidInjectionModule而不是ApplicationComponent

@Singleton
@Component(modules = [(AndroidSupportInjectionModule::class), (AppModule::class), (SplashActivityModule::class)])
interface ApplicationComponent {

    @Component.Builder
    interface Builder {

        @BindsInstance
        fun application(application: Application): Builder

        fun build(): ApplicationComponent
    }

    fun inject(kotlinApplication: KotlinApplication)
}

答案 1 :(得分:0)

一切都正确连线。我做错了什么,

ApplicationComponent中我添加了AndroidInjectionModule,这只适用于从Android Framework注入片段。

查看 AndroidInjectionModule 的来源:

package dagger.android;

import android.app.Activity;
import android.app.Fragment;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.ContentProvider;
import dagger.Module;
import dagger.internal.Beta;
import dagger.multibindings.Multibinds;
import java.util.Map;

/**
 * Contains bindings to ensure the usability of {@code dagger.android} framework classes. This
 * module should be installed in the component that is used to inject the {@link
 * android.app.Application} class.
 */
@Beta
@Module
public abstract class AndroidInjectionModule {
  @Multibinds
  abstract Map<Class<? extends Activity>, AndroidInjector.Factory<? extends Activity>>
      activityInjectorFactories();

  @Multibinds
  abstract Map<Class<? extends Fragment>, AndroidInjector.Factory<? extends Fragment>>
      fragmentInjectorFactories();

  @Multibinds
  abstract Map<Class<? extends Service>, AndroidInjector.Factory<? extends Service>>
      serviceInjectorFactories();

  @Multibinds
  abstract Map<
          Class<? extends BroadcastReceiver>, AndroidInjector.Factory<? extends BroadcastReceiver>>
      broadcastReceiverInjectorFactories();

  @Multibinds
  abstract Map<
          Class<? extends ContentProvider>, AndroidInjector.Factory<? extends ContentProvider>>
      contentProviderInjectorFactories();

  private AndroidInjectionModule() {}
}

没有提及支持库中的碎片。

现在,如果我们查看 AndroidSupportInjectionModule 的来源:

package dagger.android.support;

import android.support.v4.app.Fragment;
import dagger.Module;
import dagger.android.AndroidInjectionModule;
import dagger.android.AndroidInjector;
import dagger.internal.Beta;
import dagger.multibindings.Multibinds;
import java.util.Map;

/**
 * Configures bindings to ensure the usability of {@code dagger.android} and {@code
 * dagger.android.support} framework classes. This module should be installed in the root-most
 * component which will use these types.
 */
@Beta
@Module(includes = AndroidInjectionModule.class)
public abstract class AndroidSupportInjectionModule {
  @Multibinds
  abstract Map<Class<? extends Fragment>, AndroidInjector.Factory<? extends Fragment>>
      supportFragmentInjectorFactories();

  private AndroidSupportInjectionModule() {}
}

它包括从支持库中注入Fragment的支持。

如果您发现,AndroidSupportInjectionModule还包含AndroidInjectionModule。因此,仅包括AndroidSupportInjectionModule将完美地运作。

我的BaseActivity正在实施HasSupportFragmentInjector,它仅适用于支持片段。 ApplicationComponent中没有包含可以从支持库提供Fragment依赖关系的模块,这是主要问题。