Kotlin Error: Dagger does not support injection into private fields

AndroidDependency InjectionKotlinDagger 2Dagger

Android Problem Overview


I use in kotlin activity ViewPager and I want in Kotlin Fragment use the dagger injection. I have got Error: Dagger does not support injection into private fields. In Java Fragment the dagger injection work. Why can i not inject dagger in kotlin faragment ?

in my kotlin 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]
        }
    }

my kotlin fragment

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

Android Solutions


Solution 1 - Android

You have mistake here:

    @Inject
internal var mSharedPreferences: SharedPreferences? = null

This looks like you added @Inject annotation to the KotlinFragment class

Please change it to this and it will work:

var mSharedPreferences: SharedPreferences? = null
        @Inject set

Here is the link to the documentation: https://kotlinlang.org/docs/reference/annotations.html

Solution 2 - Android

Accidentally I came across to my own answer and have to confess, that in fact it isn't working (at least for my use-case). Please consider Avilio's answer which worked for me also: substitute internal with lateinit.


Old answer

Remove internal modifier. Dagger needs at least package-private access in order to access annotated field. In Kotlin internal modifier is not a substitution for Java's package-private access modifier.

For detailed explanation of differences between modifiers in Java and Kotlin refer to Fragmented podcast's episode #101 - "Learning Kotlin – visibility modifiers, internal modifier, modules", as well as the official docs.

Solution 3 - Android

As simple you can do this, change this line

@Inject
internal var mSharedPreferences: SharedPreferences? = null

To

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

this work like charm in my case.

Solution 4 - Android

I had the same error, even upon removing the internal keyword. So I replaced internal with lateinit and it worked.

Solution 5 - Android

@Inject
lateinit var mSharedPreferences: SharedPreferences

Also, this worked for me as well for late initialization variable

Solution 6 - Android

I followed the above advise of not making the field internal. But, that was not enough. Kapt still converting the var to private during compilation.

I had to add the @JvmField annotation to make it behave better.

The answer I found was here: https://discuss.kotlinlang.org/t/kapt-converting-public-fields-to-private-during-compilation/11757

Solution 7 - Android

Remove the internal modifier. And I also had to declare lateinit and remove the Optional.

Solution 8 - Android

@Inject
internal var mSharedPreferences: SharedPreferences? = null

Just change this to

@Inject
lateinit var mSharedPreferences: SharedPreferences

P.S. You can't use lateinit with nullables.

Solution 9 - Android

Have you defined fun inject(fragment: KotlinFragment) in your ApplicationComponent? Because it looks like your error message is saying exactly that.

EDIT: maybe you haven't provided SharedPreferences in your Module like this:

@Module
public class AndroidModule {
    private final TimrApplication application;

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

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

Solution 10 - Android

In My case, I changed

@Inject
var locationDBWrapper: LocationDBWrapper? = null

to

@Inject
lateinit var locationDBWrapper: LocationDBWrapper

Issue got resolved

Solution 11 - Android

You can't make injected vars private, but you can make them protected, which is effectively the same in a final class (and in Kotlin classes are final by default unless you use the "open" modifier). Also, use lateinit modifier like it has been said already.

@Inject
protected lateinit var mSharedPreferences: SharedPreferences

If your class is not open, this might produce a warning in Android Studio saying "'protected' visibility is effectively 'private' in a final class" - you can just suppress that with:

@Suppress("ProtectedInFinal")

Solution 12 - Android

After updating to Android Studio 3.5, most of the answers don't work. The consolidated solution is :

1. If you want to use lateinit:

@Inject lateinit var mSharedPreferences: SharedPreferences

2. If you don't want to use lateinit:

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

OR

@Inject
@JvmField
var mSharedPreferences: SharedPreferences

NOTE: These methods don't work anymore. You get the error not a valid name: <set-?>Provide

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

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestioneurosecomView Question on Stackoverflow
Solution 1 - AndroidDanylo VolokhView Answer on Stackoverflow
Solution 2 - AndroidazizbekianView Answer on Stackoverflow
Solution 3 - AndroidHemant ParmarView Answer on Stackoverflow
Solution 4 - AndroidAvilioView Answer on Stackoverflow
Solution 5 - Android0xAliHnView Answer on Stackoverflow
Solution 6 - AndroidG KView Answer on Stackoverflow
Solution 7 - AndroidFederico HeilandView Answer on Stackoverflow
Solution 8 - AndroidshivangView Answer on Stackoverflow
Solution 9 - AndroidfinkiView Answer on Stackoverflow
Solution 10 - AndroidTarun AView Answer on Stackoverflow
Solution 11 - AndroidSergeView Answer on Stackoverflow
Solution 12 - Androidankuranurag2View Answer on Stackoverflow