UninitializedPropertyAccessException:lateinit 属性尚未初始化

Posted

技术标签:

【中文标题】UninitializedPropertyAccessException:lateinit 属性尚未初始化【英文标题】:UninitializedPropertyAccessException: lateinit property has not been initialized 【发布时间】:2019-12-02 14:16:33 【问题描述】:

我有一个注入 ViewModel + ViewModel 工厂的类,当在活动的 onCreate 方法中初始化视图模型时,它表示传递的值未初始化。

下面是我的代码

我对 Kotlin 还很陌生,所以尝试过调试,但被困在这个问题上。

这是 MainActivity 代码:

class MainActivity: AppCompatActivity(), RepoSelectedListener 


    @Inject
    lateinit var viewModel: MainActivityListViewModel

    lateinit var lifecycleOwner: LifecycleOwner
    lateinit var repoSelectedListener: RepoSelectedListener

    @Inject
    lateinit var repository: RepoRepository


    override fun onCreate(savedInstanceState: Bundle?) 
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        viewModel = ViewModelProviders.of(this, ViewModelFactory(repository)).get(MainActivityListViewModel::class.java)

        repoRecyclerView.apply 
            layoutManager = LinearLayoutManager(context)
            adapter = RepoListAdapter(viewModel, lifecycleOwner, repoSelectedListener)
        


**My ViewModel:**



   class MainActivityListViewModel @Inject constructor(val 
    repoRepository: RepoRepository): BaseViewModel() 

    //private lateinit var repoRepository: RepoRepository
    private var disposable: CompositeDisposable? = null

    private val repos = MutableLiveData<List<Repo>>()
    private val repoLoadError = MutableLiveData<Boolean>()
    private val loading = MutableLiveData<Boolean>()


     init 
        disposable = CompositeDisposable()
        fetchRepos()
      

     fun getRepos(): LiveData<List<Repo>> 
        return repos
     
    

我的 ViewModelFactory:

   class ViewModelFactory @Inject constructor(private val 
   repoRepository: RepoRepository): ViewModelProvider.Factory


    override fun <T : ViewModel?> create(modelClass: Class<T>): T 
        if 
   (modelClass.isAssignableFrom(MainActivityListViewModel::class.java)) 
   
            @Suppress("UNCHECKED_CAST")
            return MainActivityListViewModel(this.repoRepository) as T
        
        throw IllegalArgumentException("Unknown ViewModel class")

    


   

我的班级回购:

  class RepoRepository @Inject constructor(private val githubRepos: 
    GithubRepos)


    private lateinit var repoService: GithubRepos


    fun getRepositories(): Single<List<Repo>> 
        return repoService.getRepos()
    

    fun getSingleRepo(owner: String, name: String): Single<Repo> 
        return repoService.getSingleRepo(owner, name)
    
   

这是我收到的错误:

   Unable to start activity ComponentInfocom.carllewis14.repos/com.carllewis14.repos.ui.MainActivity: kotlin.UninitializedPropertyAccessException: lateinit property 
  repository has not been initialized

【问题讨论】:

您正在访问的变量(存储库)必须存在,但它不是一次初始化的,使其成为可选或在使用前初始化它 您应该将 RepoRepository 注入到您的活动中。或者注入 MainActivityListViewModel 并从 viewmodel 访问你的 repo。 @AlexandrKolesnik 我要如何在使用前进行初始化 @EnsarBayhan MainActivityListViewModel 已经注入 @DanYon Yo 必须注入到您的 MainActivity。 【参考方案1】:

这是因为您在使用实例初始化之前尝试使用存储库而不检查其初始化。

在该变量中使用lateinit nullity cannot be used 时。

lateinit var repository: RepoRepository

然后,在使用对象的任何方法之前,检查它是否已初始化:

if (::repository.isInitialized)

GL

【讨论】:

lateinit 不允许用于可空类型 那么 isInitialized 就像一个空检查。为什么不在这些情况下使用可为空的属性?【参考方案2】:

在这里看看我的回答(也许有帮助)Nullable var with `?` vs. lateinit var

基本上,您永远不会初始化您的repository: RepoRepository

根据您编写的代码,您的活动中也不需要存储库的实例,它应该只在 ViewModel 的构造函数中创建(具有注入)

private lateinit var repoService: GithubRepos 也会遇到类似的问题;如果它在对象的构造函数中,则不必再次声明。

【讨论】:

只是为了澄清我不需要在我的活动中注入repository: RepoRepository,因为它注入了我的视图模型?所以我应该将视图模型创建为viewModel = ViewModelProviders.of(this).get(MainActivityListViewModel::class.java) 吗?就好像我包含我的 viewmodelfactory 一样:` viewModel = ViewModelProviders.of(this, ViewModelFactory(repository)).get(MainActivityListViewModel::class.java)` 然后我必须添加实例,因为它出现在我的 viewmodel 工厂构造函数中跨度> 好的,让我试试,然后回复你@a_local_nobody 我感谢你的帮助【参考方案3】:

似乎问题代码掩盖了注入 供参考 你也可以通过惰性初始化:

要创建一个在第一次访问时初始化的对象,我们可以使用惰性方法:

val lazyValue: ClassWithHeavyInitialization by lazy 
        numberOfInitializations.incrementAndGet()
        ClassWithHeavyInitialization()
    

https://www.baeldung.com/kotlin-lazy-initialization 另请参阅 kotlin 文档

【讨论】:

【参考方案4】:

如果您使用的是 Kotlin 1.2,您可以轻松检查是否已初始化 lateinit 变量。如果不是,那么,您始终可以使用 not null 方法。

无论如何,您可以通过以下方式检查是否已初始化 lateinit var:

if (::fullName.isInitialized) 
    print("Hi, $fullName")

【讨论】:

以上是关于UninitializedPropertyAccessException:lateinit 属性尚未初始化的主要内容,如果未能解决你的问题,请参考以下文章