Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

UninitializedPropertyAccessException: lateinit property pref has not been initialized

I know a similar question has been answered Here. But that was due to butter knife library problem but my case is different. In my case when I use dagger injected properties in my base activity it shows me error Caused by: kotlin.UninitializedPropertyAccessException: lateinit property pref has not been initialized

But the same property when I use in my sub activity (Login activity) it works fine.

eg. pref.setLanguage("abc") -> it works fine in login activity but throws error in base activity

Here is my code:

BaseActivity

    abstract class BaseActivity : AppCompatActivity() {     @Inject     lateinit var pref: AppSharedPreferences     @Inject     lateinit var utils: Utils     lateinit var mCurrentLanguage: String     protected lateinit var progressBarUtils: ProgressBarUtils      override fun onCreate(savedInstanceState: Bundle?) {         super.onCreate(savedInstanceState)         progressBarUtils = ProgressBarUtils(this)         mCurrentLanguage = "EN"         pref.setSelectedLanguage(mCurrentLanguage)        }     } 

LoginActivity

    class LoginActivity : BaseActivity() {     private val TAG = this.javaClass.name     lateinit var loginViewModel: LoginViewModel     @Inject     lateinit var viewModelFactory: LoginViewModelFactory       override fun onCreate(savedInstanceState: Bundle?) {         super.onCreate(savedInstanceState)         setContentView(R.layout.activity_login)         AndroidInjection.inject(this)         loginViewModel = ViewModelProviders.of(this, viewModelFactory).get(                 LoginViewModel::class.java)         loadData("abc", "xyz")         observerOnLoginResult()         observerOnLoginError()     }       private fun observerOnLoginError() {         loginViewModel.loginError().observe(this, Observer<String> {             progressBarUtils.cancelProgressDialog()             if (it != null) {                 Toast.makeText(this, resources.getString(R.string.error_message) + it,                         Toast.LENGTH_SHORT).show()             }         })     }      private fun observerOnLoginResult() {         loginViewModel.loginResult().observe(this,                 Observer<LoginModel> {                     progressBarUtils.cancelProgressDialog()                     if (it != null) {                         setData(it)                     }                 })     }      private fun setData(loginData: LoginModel) {         pref.setCurrentUserName(loginData.data.userName)     }      private fun loadData(email: String, password: String) {         progressBarUtils.showProgressDialog()         val builder = StringBuilder()         var auth = Base64.encodeToString(("$email:$password").toByteArray(), Base64.NO_WRAP)         builder.append("Basic ")         builder.append(auth)         loginViewModel.getLoginData(builder.toString())     }      override fun onDestroy() {         loginViewModel.disposeElements()         super.onDestroy()     } 

AppModule

    @Module class AppModule(val app: Application) {      @Provides     @Singleton     fun provideApplication(): Application = app       @Provides     @Singleton     fun provideSharedPreferences(): AppSharedPreferences = AppSharedPreferences(app)       @Provides     @Singleton     fun provideUtils(): Utils = Utils(app)     } 

Builder Module

    @Module abstract class BuildersModule {      @PerActivity     @ContributesAndroidInjector(modules = arrayOf(LoginModule::class))     abstract fun contributeLoginActivity(): LoginActivity      @PerActivity     abstract fun contributeBaseActivityActivity(): BaseActivity     } 

AppComponent

    @Singleton @Component(         modules = arrayOf(AndroidInjectionModule::class, AppModule::class, BuildersModule::class))      interface AppComponent {        fun inject(app: LotusApp)                 }  
like image 657
Tarun Avatar asked May 29 '18 07:05

Tarun


People also ask

What if Lateinit is not initialized?

If you try accessing Lateinit variables without initializing, it will throw an exception stating that it is not initialized or properly being accessed.

How do I know if Lateinit is initialized?

In order to avoid this situation, Kotlin introduced a new modifier called as "lateInit". Along with this modifier, Kotlin provides a couple of methods to check whether this variable is initialized or not. Use "lateInit" with a mutable variable. That means, we need use "var" keyword with "lateInit".

What happens when a field declared as lateinit is accessed before it is initialized?

Accessing a lateinit property before it has been initialized throws a special exception that clearly identifies the property being accessed and the fact that it hasn't been initialized.


1 Answers

You can't use an object before you initialize it.

override fun onCreate(savedInstanceState: Bundle?) {   super.onCreate(savedInstanceState) // prefs called in parents onCreate!   setContentView(R.layout.activity_login)   AndroidInjection.inject(this) // injection happens here 

Get your calls in order. Easiest way to fix would be to move AndroidInjection.inject(this) before the call to super.onCreate(...).

like image 136
David Medenjak Avatar answered Sep 21 '22 14:09

David Medenjak