Ошибка Kotlin: 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]
}
}
мой котлин фрагмент
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
12 ответов
Случайно я наткнулся на свой собственный ответ и должен признаться, что на самом деле он не работает (по крайней мере, для моего варианта использования). Пожалуйста, примите во внимание ответ Авилио, который также помог мне: заменить internal
с lateinit
,
Старый ответ
Удалить internal
модификатор. Для доступа к аннотированному полю Dagger необходим как минимум частный доступ к пакету. В котлине internal
Модификатор не является заменой для модификатора закрытого доступа Java.
Подробное объяснение различий между модификаторами в Java и Kotlin см. В эпизоде фрагментированного подкаста № 101 - "Изучение Kotlin - модификаторы видимости, внутренний модификатор, модули", а также в официальных документах.
Вы ошиблись здесь:
@Inject
internal var mSharedPreferences: SharedPreferences? = null
Похоже, вы добавили @Inject
аннотация к KotlinFragment
учебный класс
Пожалуйста, измените это на это, и это будет работать:
var mSharedPreferences: SharedPreferences? = null
@Inject set
Вот ссылка на документацию: https://kotlinlang.org/docs/reference/annotations.html
Как просто вы можете сделать это, измените эту строку
@Inject
internal var mSharedPreferences: SharedPreferences? = null
к
@set:Inject
internal var mSharedPreferences: SharedPreferences? = null
эта работа как шарм в моем случае.
У меня была такая же ошибка, даже после удаления внутреннего ключевого слова. Поэтому я заменил внутренний на lateinit, и это сработало.
@Inject
lateinit var mSharedPreferences: SharedPreferences
Кроме того, это сработало и для поздней инициализации переменной
Я последовал приведенному выше совету не делать поле внутренним. Но этого было недостаточно. Kapt все еще преобразует переменную в частную во время компиляции.
Мне пришлось добавить @JvmField
аннотацию, чтобы она работала лучше.
Ответ, который я нашел, был здесь: https://discuss.kotlinlang.org/t/kapt-converting-public-fields-to-private-during-compilation/11757
@Inject
internal var mSharedPreferences: SharedPreferences? = null
Просто изменил это на
@Inject
lateinit var mSharedPreferences: SharedPreferences
PS Вы не можете использовать lateinit с нулевыми значениями.
Удалить internal
модификатор. И я также должен был объявить lateinit
и удалите Необязательный.
В моем случае я изменил
@Inject
var locationDBWrapper: LocationDBWrapper? = null
к
@Inject
lateinit var locationDBWrapper: LocationDBWrapper
Проблема решена
Вы определили 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);
}
}
После обновления до Android Studio 3.5 большинство ответов не работают. Консолидированное решение:
1. Если вы хотите использовать:
@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
Вы не можете сделать внедренные вары частными, но вы можете сделать их защищенными, что фактически то же самое в последнем классе (а в Kotlin классы являются окончательными по умолчанию, если вы не используете модификатор «open»). Также используйте модификатор lateinit, как уже было сказано.
@Inject
protected lateinit var mSharedPreferences: SharedPreferences
Если ваш класс не открыт, в Android Studio может появиться предупреждение о том, что «защищенная» видимость фактически является «частной» в последнем классе »- вы можете просто подавить это с помощью:
@Suppress("ProtectedInFinal")