Dagger注入lateinit属性pref在BaseActivity未初始化,LoginActivity正常
嘿,我一眼就看出问题出在哪了——你调用Dagger注入的时机太晚了!
问题原因拆解
看你的LoginActivity代码,你是先调用super.onCreate(savedInstanceState)(也就是先执行BaseActivity的onCreate逻辑),之后才执行AndroidInjection.inject(this)完成注入。这就导致BaseActivity的onCreate里调用pref.setSelectedLanguage(mCurrentLanguage)时,pref还没被Dagger初始化,自然抛出UninitializedPropertyAccessException;而LoginActivity里的pref.setCurrentUserName是在注入完成后才执行的,所以完全没问题。
两步搞定解决方案
你只需要把注入的时机提前到BaseActivity的onCreate执行之前就行,具体这么改:
第一步:修改BaseActivity的onCreate顺序
把AndroidInjection.inject(this)放到super.onCreate(savedInstanceState)之前,确保注入完成后再执行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?) { // 先完成Dagger注入,再执行父类的onCreate AndroidInjection.inject(this) super.onCreate(savedInstanceState) progressBarUtils = ProgressBarUtils(this) mCurrentLanguage = "EN" pref.setSelectedLanguage(mCurrentLanguage) // 现在pref已经被正确初始化啦 } }
第二步:移除LoginActivity里的重复注入
既然BaseActivity已经处理了注入,LoginActivity里就不需要再调用AndroidInjection.inject(this)了,删掉这行就行:
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) // 此时BaseActivity已经完成所有注入 setContentView(R.layout.activity_login) loginViewModel = ViewModelProviders.of(this, viewModelFactory).get( LoginViewModel::class.java) loadData("abc", "xyz") observerOnLoginResult() observerOnLoginError() } // ...你的其他方法保持不变 }
额外小提示
看你的BuildersModule里有contributeBaseActivityActivity()的配置,但因为BaseActivity是抽象类,其实不需要单独给它配置@ContributesAndroidInjector——子类LoginActivity的注入器已经能继承到AppModule提供的单例依赖(比如pref和utils),所以这个配置可以删掉,不会影响功能。
内容的提问来源于stack exchange,提问作者Tarun

