54 votes

Erreur Kotlin : Dagger ne prend pas en charge l'injection dans les champs privés

J'utilise dans l'activité kotlin ViewPager et je veux dans Kotlin Fragment utiliser l'injection dagger. J'ai obtenu l'erreur : Dagger ne prend pas en charge l'injection dans les champs privés. Dans Java Fragment, l'injection de dagger fonctionne. Pourquoi ne puis-je pas injecter Dagger dans Kotlin Fragment ?

dans mon activité 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]
        }
    }

mon fragment de 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
}

}

messages gradle build

enter image description here

1 votes

C'est un défaut de Dagger en général - il ne peut pas accéder aux champs privés. Cela nécessiterait une réflexion et serait impossible à faire au moment de la compilation comme Dagger le préfère. Le faire au moment de l'exécution coûterait du temps de chargement pour faire des appels réfléchis. Donc, il ne le supporte pas du tout.

59voto

andranikAzizbekyan Points 727

J'ai accidentellement trouvé ma propre réponse et je dois avouer qu'en fait, elle ne fonctionne pas (du moins pour mon cas d'utilisation). Veuillez considérer La réponse d'Avilio qui a également fonctionné pour moi : substitut internal avec lateinit .


Ancienne réponse

Retirer internal modificateur. Dagger a besoin d'un accès au moins privé au paquet afin d'accéder au champ annoté. En Kotlin internal Le modificateur est pas une substitution pour le modificateur d'accès privé par paquet de Java.

Pour une explication détaillée des différences entre les modificateurs en Java et en Kotlin, reportez-vous à l'article de Fragmented podcast. épisode #101 - "Apprendre Kotlin - modificateurs de visibilité, modificateur interne, modules" ainsi que le documents officiels .

0 votes

J'ai publié les messages de construction de Gradle. Je ne comprends pas quel champ privé pose problème.

1 votes

Le message d'erreur a été remplacé par un autre, qui diffère de votre question initiale. Reportez-vous à d'autres questions similaires.

0 votes

Merci de votre aide. J'ai modifié ma question pour revenir à l'original.

59voto

Danylo Volokh Points 151

Vous faites erreur :

    @Inject
internal var mSharedPreferences: SharedPreferences? = null

On dirait que tu as ajouté @Inject à l'annotation KotlinFragment classe

Veuillez le changer en ceci et il fonctionnera :

var mSharedPreferences: SharedPreferences? = null
        @Inject set

Voici le lien vers la documentation : https://kotlinlang.org/docs/reference/annotations.html

0 votes

Merci beaucoup. Je peux ajouter qu'en cas d'injection, il peut être utile d'annoter le paramètre du setter. Par exemple, si vous voulez injecter deux String et vous les différenciez avec @Qualifier le définisseur doit disposer de cette information : @Inject set(@CustomAnnotation param) { field = param } .

5 votes

Vous pouvez aussi : @set:Inject var mSharedPreferences: SharedPreferences? = null

0 votes

@AndrzejZabost (y)

36voto

Hemant Parmar Points 2285

Aussi simple que cela puisse être, changez cette ligne

@Inject
internal var mSharedPreferences: SharedPreferences? = null

A

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

cela fonctionne comme un charme dans mon cas.

2 votes

Merci ! Cela fonctionne pour moi pour injecter un type primitif comme integer.

2 votes

Joli, il fonctionne comme un charme, merci !

33voto

Avilio Points 311

J'ai eu la même erreur, même en supprimant le mot-clé interne. J'ai donc remplacé interne avec lateinit et ça a marché.

1 votes

Notez que lateinit ne permet pas les types nullables ( ? type). Pour un champ nullable, veuillez utiliser Provider ou Lazy. Le type enveloppé peut être nullable.

1 votes

Cela semble très étrange, pourquoi cela fonctionne-t-il ? Dagger se plaint de la var être private (ce qui n'est pas le cas), et le rendre lateinit répare ça ? Pourquoi ?

9voto

0xalihn Points 5358
@Inject
lateinit var mSharedPreferences: SharedPreferences

Cela a également fonctionné pour moi pour la variable d'initialisation tardive.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X