Kotlin Error: Dagger does not support injection into private fields
Kotlin Error: Dagger does not support injection into private fields
我在 kotlin 中使用 activity ViewPager,我想在 Kotlin Fragment 中使用匕首注入。我有错误:Dagger 不支持注入私有字段。
在Java Fragment中匕首注入工作。
为什么我不能在 kotlin faragment 中注入匕首?
在我的科特林中 activity
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]
}
}
我的科特林片段
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构建
我偶然发现了自己的答案,不得不承认,实际上它不起作用(至少对于我的用例而言)。请考虑对我也有用的 :将 internal
替换为 lateinit
.
旧答案
删除 internal
修饰符。 Dagger 至少需要包私有访问权限才能访问带注释的字段。在 Kotlin 中,internal
修饰符 而不是 替代 Java 的包私有访问修饰符。
有关 Java 和 Kotlin 中修饰符之间差异的详细说明,请参阅 Fragmented podcast 的 episode #101 - "Learning Kotlin – visibility modifiers, internal modifier, modules", as well as the official docs。
你在ApplicationComponent
中定义了fun inject(fragment: KotlinFragment)
了吗?因为看起来你的错误信息就是这么说的。
编辑:也许您没有像这样在您的模块中提供 SharedPreferences
:
@Module
public class AndroidModule {
private final TimrApplication application;
public AndroidModule(TimrApplication application) {
this.application = application;
}
@Provides
SharedPreferences provideSharedPreferences(){
return PreferenceManager.getDefaultSharedPreferences(application);
}
}
你这里有误:
@Inject
internal var mSharedPreferences: SharedPreferences? = null
您似乎在 KotlinFragment
class
中添加了 @Inject
注释
请改成这样,它会起作用:
var mSharedPreferences: SharedPreferences? = null
@Inject set
这是文档的 link:https://kotlinlang.org/docs/reference/annotations.html
即使删除了内部关键字,我也遇到了同样的错误。所以我用 lateinit 替换了 internal 并且它起作用了。
删除 internal
修饰符。而且我还必须声明 lateinit
并删除 Optional。
很简单,你可以这样做,改变这一行
@Inject
internal var mSharedPreferences: SharedPreferences? = null
至
@set:Inject
internal var mSharedPreferences: SharedPreferences? = null
这对我来说很有魅力。
@Inject
lateinit var mSharedPreferences: SharedPreferences
此外,这对我也适用于后期初始化变量
我遵循了上面的建议,没有将字段设为内部。但是,这还不够。 Kapt 在编译期间仍然将 var 转换为 private。
我不得不添加 @JvmField
注释以使其表现更好。
我找到的答案在这里:
https://discuss.kotlinlang.org/t/kapt-converting-public-fields-to-private-during-compilation/11757
在我的例子中,我改变了
@Inject
var locationDBWrapper: LocationDBWrapper? = null
至
@Inject
lateinit var locationDBWrapper: LocationDBWrapper
问题已解决
您不能将注入的变量设为私有,但可以将它们设为受保护,这在最终 class 中实际上是相同的(在 Kotlin 中 classes 默认是最终的,除非您使用“打开”修饰符)。另外,像已经说过的那样使用 lateinit 修饰符。
@Inject
protected lateinit var mSharedPreferences: SharedPreferences
如果您的 class 未打开,这可能会在 Android Studio 中产生警告,提示“'protected' 可见性在最终 class 中有效 'private' ]" - 你可以通过以下方式抑制它:
@Suppress("ProtectedInFinal")
更新到AndroidStudio 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
@Inject
internal var mSharedPreferences: SharedPreferences? = null
只需将其更改为
@Inject
lateinit var mSharedPreferences: SharedPreferences
P.S。您不能将 lateinit 与可空值一起使用。
我在 kotlin 中使用 activity ViewPager,我想在 Kotlin Fragment 中使用匕首注入。我有错误:Dagger 不支持注入私有字段。 在Java Fragment中匕首注入工作。 为什么我不能在 kotlin faragment 中注入匕首?
在我的科特林中 activity
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]
}
}
我的科特林片段
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构建
我偶然发现了自己的答案,不得不承认,实际上它不起作用(至少对于我的用例而言)。请考虑对我也有用的 internal
替换为 lateinit
.
旧答案
删除 internal
修饰符。 Dagger 至少需要包私有访问权限才能访问带注释的字段。在 Kotlin 中,internal
修饰符 而不是 替代 Java 的包私有访问修饰符。
有关 Java 和 Kotlin 中修饰符之间差异的详细说明,请参阅 Fragmented podcast 的 episode #101 - "Learning Kotlin – visibility modifiers, internal modifier, modules", as well as the official docs。
你在ApplicationComponent
中定义了fun inject(fragment: KotlinFragment)
了吗?因为看起来你的错误信息就是这么说的。
编辑:也许您没有像这样在您的模块中提供 SharedPreferences
:
@Module
public class AndroidModule {
private final TimrApplication application;
public AndroidModule(TimrApplication application) {
this.application = application;
}
@Provides
SharedPreferences provideSharedPreferences(){
return PreferenceManager.getDefaultSharedPreferences(application);
}
}
你这里有误:
@Inject
internal var mSharedPreferences: SharedPreferences? = null
您似乎在 KotlinFragment
class
@Inject
注释
请改成这样,它会起作用:
var mSharedPreferences: SharedPreferences? = null
@Inject set
这是文档的 link:https://kotlinlang.org/docs/reference/annotations.html
即使删除了内部关键字,我也遇到了同样的错误。所以我用 lateinit 替换了 internal 并且它起作用了。
删除 internal
修饰符。而且我还必须声明 lateinit
并删除 Optional。
很简单,你可以这样做,改变这一行
@Inject
internal var mSharedPreferences: SharedPreferences? = null
至
@set:Inject
internal var mSharedPreferences: SharedPreferences? = null
这对我来说很有魅力。
@Inject
lateinit var mSharedPreferences: SharedPreferences
此外,这对我也适用于后期初始化变量
我遵循了上面的建议,没有将字段设为内部。但是,这还不够。 Kapt 在编译期间仍然将 var 转换为 private。
我不得不添加 @JvmField
注释以使其表现更好。
我找到的答案在这里: https://discuss.kotlinlang.org/t/kapt-converting-public-fields-to-private-during-compilation/11757
在我的例子中,我改变了
@Inject
var locationDBWrapper: LocationDBWrapper? = null
至
@Inject
lateinit var locationDBWrapper: LocationDBWrapper
问题已解决
您不能将注入的变量设为私有,但可以将它们设为受保护,这在最终 class 中实际上是相同的(在 Kotlin 中 classes 默认是最终的,除非您使用“打开”修饰符)。另外,像已经说过的那样使用 lateinit 修饰符。
@Inject
protected lateinit var mSharedPreferences: SharedPreferences
如果您的 class 未打开,这可能会在 Android Studio 中产生警告,提示“'protected' 可见性在最终 class 中有效 'private' ]" - 你可以通过以下方式抑制它:
@Suppress("ProtectedInFinal")
更新到AndroidStudio 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
@Inject
internal var mSharedPreferences: SharedPreferences? = null
只需将其更改为
@Inject
lateinit var mSharedPreferences: SharedPreferences
P.S。您不能将 lateinit 与可空值一起使用。