我在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
答案 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 一起使用。