You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

添加NavHostFragment后笔记应用启动失败,报UninitializedPropertyAccessException

解决lateinit属性binding未初始化的异常问题

问题概述

跟随Plural Sight课程开发笔记管理应用,包含两个Activity。编译成功但应用无法启动,添加NavHostFragment后仍抛出kotlin.UninitializedPropertyAccessException,提示lateinit属性binding未初始化。

Logcat错误信息

Launching 'app' on Pixel 6 API 33.
Install successfully finished in 6 s 713 ms.
$ adb shell am start -n "com.example.nokeeper4/com.example.nokeeper4.NoteListActivity" -a android.intent.action.MAIN -c android.intent.category.LAUNCHER
Connected to process 3595 on device 'Pixel_6_API_33 [emulator-5554]'.
...
E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.example.nokeeper4, PID: 3595
    java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.nokeeper4/com.example.nokeeper4.NoteListActivity}: kotlin.UninitializedPropertyAccessException: lateinit property binding has not been initialized
...

相关代码

MainActivity XML代码

<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
    <com.google.android.material.appbar.AppBarLayout
        android:id="@+id/appbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:theme="@style/Theme.Nokeeper4.AppBarOverlay">
        <androidx.appcompat.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="?attr/colorPrimary"
            app:popupTheme="@style/Theme.Nokeeper4.PopupOverlay" />
    </com.google.android.material.appbar.AppBarLayout>
    <androidx.fragment.app.FragmentContainerView
        android:id="@+id/nav_host_frag"
        android:name="androidx.navigation.fragment.NavHostFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior"
        app:navGraph="@navigation/nav_graph2"
        tools:layout="@layout/activity_main"/>
    <include
        android:id="@+id/contentMain"
        layout="@layout/content_main" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>

NoteListActivity XML代码

<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".NoteListActivity">
    <com.google.android.material.appbar.AppBarLayout
        android:id="@+id/appbar"
        android:layout_height="100dp"
        android:layout_width="match_parent">
        <androidx.appcompat.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_height="?attr/actionBarSize"
            android:layout_width="match_parent" />
    </com.google.android.material.appbar.AppBarLayout>
    <com.google.android.material.floatingactionbutton.FloatingActionButton
        android:id="@+id/fab"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom|end"
        android:layout_margin="16dp"
        android:contentDescription="@string/new_note"
        android:src="@drawable/baseline_add_white_24"
        app:backgroundTint="#9C27B0" />
    <androidx.fragment.app.FragmentContainerView
        android:id="@+id/nav_host_frag"
        android:name="androidx.navigation.fragment.NavHostFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:defaultNavHost="true"
        app:layout_behavior="@string/appbar_scrolling_view_behavior"
        app:navGraph="@navigation/nav_graph2"
        tools:layout="@layout/activity_note_list"/>
    <include
        android:id="@+id/contentNoteList"
        layout="@layout/content_note_list" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>

MainActivity.kt代码

class MainActivity : AppCompatActivity() {
    private var notePosition = POSITION_NOT_SET
    private lateinit var spinnerCourses:  Spinner
    private lateinit var textNoteTitle: EditText
    private lateinit var textNoteText: EditText
    private lateinit var binding: ActivityMainBinding
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(binding.root)
        binding = ActivityMainBinding.inflate(layoutInflater)
        setSupportActionBar(binding.toolbar)
        spinnerCourses = findViewById(R.id.spinnerCourses)
        textNoteTitle = findViewById(R.id.textNoteTitle)
        textNoteText = findViewById(R.id.textNoteText)
        val adapterCourses = ArrayAdapter<CourseInfo>(this,
                android.R.layout.simple_spinner_item,
                DataManager.courses.values.toList())
        adapterCourses.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
        spinnerCourses.adapter = adapterCourses
        notePosition = savedInstanceState?.getInt(NOTE_POSITION, POSITION_NOT_SET) ?: intent.getIntExtra(NOTE_POSITION,POSITION_NOT_SET)
        if (notePosition != POSITION_NOT_SET)
            displayNote()
        else{
            DataManager.notes.add(NoteInfo())
            notePosition = DataManager.notes.lastIndex
        }
    }
    ...
}

NoteListActivity.kt代码

class NoteListActivity : AppCompatActivity() {
    private lateinit var binding: ActivityNoteListBinding
    private lateinit var listNotes: ListView
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(binding.root)
        binding = ActivityNoteListBinding.inflate(layoutInflater)
        listNotes = findViewById(R.id.listNotes)
        binding.fab.setOnClickListener {
            val activityIntent = Intent(this, MainActivity::class.java)
            startActivity(activityIntent)
        }
        listNotes.adapter = ArrayAdapter(
            this,
            android.R.layout.simple_list_item_1,
            DataManager.notes)
        listNotes.setOnItemClickListener { _, _, position, _ ->
            val activityIntent = Intent(this, MainActivity::class.java)
            activityIntent.putExtra(NOTE_POSITION, position)
            startActivity(activityIntent)
        }
    }
    ...
}

解决方案

核心问题

异常的原因是初始化binding的顺序错误:在调用setContentView(binding.root)时,binding变量还未被赋值(lateinit属性必须先初始化才能使用),直接访问binding.root会触发未初始化异常。

修正代码

修改MainActivity的onCreate方法

将binding = ActivityMainBinding.inflate(layoutInflater)移到setContentView(binding.root)之前,同时优化视图获取方式(直接通过binding获取,无需再调用findViewById):

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    binding = ActivityMainBinding.inflate(layoutInflater)
    setContentView(binding.root)
    setSupportActionBar(binding.toolbar)
    // 直接通过binding获取视图,替代findViewById
    spinnerCourses = binding.spinnerCourses
    textNoteTitle = binding.textNoteTitle
    textNoteText = binding.textNoteText
    val adapterCourses = ArrayAdapter<CourseInfo>(this,
            android.R.layout.simple_spinner_item,
            DataManager.courses.values.toList())
    adapterCourses.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
    spinnerCourses.adapter = adapterCourses
    notePosition = savedInstanceState?.getInt(NOTE_POSITION, POSITION_NOT_SET) ?: intent.getIntExtra(NOTE_POSITION,POSITION_NOT_SET)
    if (notePosition != POSITION_NOT_SET)
        displayNote()
    else{
        DataManager.notes.add(NoteInfo())
        notePosition = DataManager.notes.lastIndex
    }
}

修改NoteListActivity的onCreate方法

同样调整binding初始化顺序,并通过binding获取ListView:

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    binding = ActivityNoteListBinding.inflate(layoutInflater)
    setContentView(binding.root)
    // 直接通过binding获取ListView
    listNotes = binding.listNotes
    binding.fab.setOnClickListener {
        val activityIntent = Intent(this, MainActivity::class.java)
        startActivity(activityIntent)
    }
    listNotes.adapter = ArrayAdapter(
        this,
        android.R.layout.simple_list_item_1,
        DataManager.notes)
    listNotes.setOnItemClickListener { _, _, position, _ ->
        val activityIntent = Intent(this, MainActivity::class.java)
        activityIntent.putExtra(NOTE_POSITION, position)
        startActivity(activityIntent)
    }
}

额外说明

使用View Binding时,正确的流程是:

  1. 通过BindingClass.inflate(layoutInflater)初始化binding对象
  2. 调用setContentView(binding.root)设置布局
  3. 通过binding对象直接访问布局中的视图,无需使用findViewById

内容的提问来源于stack exchange,提问作者atiku

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 17:00:07