Kotlin错误:Dagger不支持注入私人领域

时间:2017-11-08 19:03:10

标签: android dependency-injection kotlin dagger-2 dagger

我在kotlin活动中使用ViewPager,我想在Kotlin Fragment中使用匕首注射。我有错误:Dagger不支持注入私有字段。 在Java Fragment中匕首注射工作。 为什么我不能在kotlin faragment中注入匕首?

在我的kotlin活动中

mPagerAdapter = object : FragmentPagerAdapter(supportFragmentManager) {

        private val mFragments = arrayOf(KotlinFragment(), JavaFragment())
        private val mFragmentNames = arrayOf(getString(R.string.cashdocuments), getString(R.string.action_absmysql))

        override fun getItem(position: Int): Fragment {
            return mFragments[position]
        }

        override fun getCount(): Int {
            return mFragments.size
        }

        override fun getPageTitle(position: Int): CharSequence {
            return mFragmentNames[position]
        }
    }

我的kotlin片段

class KotlinFragment : Fragment()  {


@Inject
internal var mSharedPreferences: SharedPreferences? = null

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

    (activity.application as SamfantozziApp).dgaeacomponent().inject(this)

}

override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?,
                          savedInstanceState: Bundle?): View? {
    super.onCreateView(inflater, container, savedInstanceState)
    val rootView = inflater!!.inflate(R.layout.activity_absserver, container, false)

    return rootView
}

}

消息gradle build

enter image description here

11 个答案:

答案 0 :(得分:30)

无意中,我遇到了自己的答案并且不得不承认,事实上它并不起作用(至少对我的用例而言)。请考虑对我有用的Avilio's answer:将internal替换为lateinit

旧答案

删除internal修饰符。 Dagger至少需要包私有访问才能访问带注释的字段。在Kotlin internal修饰符替换Java的包私有访问修饰符。

有关Java和Kotlin中修饰符之间差异的详细说明,请参阅Fragmented podcast' s episode #101 - "学习Kotlin - 可见性修饰符,内部修饰符,模块" ,以及official docs

答案 1 :(得分:26)

你错了:

    @Inject
internal var mSharedPreferences: SharedPreferences? = null

这似乎是您向@Inject

添加了KotlinFragment注释

请将其改为此状态,并且可以正常工作:

var mSharedPreferences: SharedPreferences? = null
        @Inject set

以下是文档的链接:https://kotlinlang.org/docs/reference/annotations.html

答案 2 :(得分:24)

即使删除了内部关键字,我也遇到了同样的错误。所以我用 lateinit 替换了内部,但它确实有效。

答案 3 :(得分:3)

@Inject
lateinit var mSharedPreferences: SharedPreferences

此外,这对于后期初始化变量也很有效

答案 4 :(得分:2)

您是否在fun inject(fragment: KotlinFragment)中定义了ApplicationComponent?因为看起来您的错误消息正好说明了这一点。

编辑:也许您没有在模块中提供SharedPreferences,如下所示:

@Module
public class AndroidModule {
    private final TimrApplication application;

    public AndroidModule(TimrApplication application) {
        this.application = application;
    }

    @Provides
    SharedPreferences provideSharedPreferences(){
        return PreferenceManager.getDefaultSharedPreferences(application);
    }
}

答案 5 :(得分:2)

删除internal修饰符。我还必须声明lateinit并删除Optional。

答案 6 :(得分:0)

我遵循以上建议,不要将字段设置为内部。但是,这还不够。 Kapt仍在编译过程中将var转换为private。

我必须添加@JvmField批注以使其表现更好。

我找到的答案在这里: https://discuss.kotlinlang.org/t/kapt-converting-public-fields-to-private-during-compilation/11757

答案 7 :(得分:0)

就我而言,我改变了

@Inject
var locationDBWrapper: LocationDBWrapper? = null

@Inject
lateinit var locationDBWrapper: LocationDBWrapper

问题已解决

答案 8 :(得分:0)

您不能将注入的变量设为私有,但您可以将它们设为受保护,这在 final 类中实际上是相同的(并且在 Kotlin 类中,默认情况下类是 final 的,除非您使用“open”修饰符)。另外,像已经说过的那样使用 lateinit 修饰符。

@Inject
protected lateinit var mSharedPreferences: SharedPreferences

如果您的课程未开放,这可能会在 Android Studio 中产生一条警告,指出“'受保护'可见性在最终课程中实际上是'私有'”-您可以使用以下方法抑制它:

@Suppress("ProtectedInFinal")

答案 9 :(得分:0)

更新到 Android Studio 3.5 后,大部分答案都不起作用。综合解决方案是:

1.如果您想使用 lateinit

@Inject lateinit var mSharedPreferences: SharedPreferences

2.如果您不想使用 lateinit

var mSharedPreferences: SharedPreferences? = null
    @Inject set(value) {
       field = value
}

@Inject
@JvmField
var mSharedPreferences: SharedPreferences

注意:这些方法不再起作用。您收到错误 not a valid name: <set-?>Provide

@set:Inject
var mSharedPreferences: SharedPreferences? = null
var mSharedPreferences: SharedPreferences? = null 
    @Inject set

答案 10 :(得分:0)

@Inject
internal var mSharedPreferences: SharedPreferences? = null

只需将其更改为

@Inject
lateinit var mSharedPreferences: SharedPreferences

附言您不能将 lateinit 与 nullables 一起使用。