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

Navigation Drawer Activity中OnClickListener崩溃,OnClick正常问题

导航抽屉Activity中使用OnClickListener崩溃问题解决

问题描述

在导航抽屉Activity的MainActivity.kt中,使用OnClickListener时应用启动即崩溃,但在onCreate函数外部使用XML绑定的OnClick方法时应用运行正常。编译无报错,但Logcat中存在空指针错误信息。

崩溃时的代码

package com.example.android.chatapplication

import android.content.Intent
import android.os.Bundle
import android.view.Menu
import android.view.View
import android.widget.Button
import android.widget.ImageButton
import com.google.android.material.snackbar.Snackbar
import com.google.android.material.navigation.NavigationView
import androidx.navigation.findNavController
import androidx.navigation.ui.AppBarConfiguration
import androidx.navigation.ui.navigateUp
import androidx.navigation.ui.setupActionBarWithNavController
import androidx.navigation.ui.setupWithNavController
import androidx.drawerlayout.widget.DrawerLayout
import androidx.appcompat.app.AppCompatActivity
import com.example.android.chatapplication.databinding.ActivityMainBinding

class MainActivity : AppCompatActivity() {

    private lateinit var appBarConfiguration: AppBarConfiguration
    private lateinit var binding: ActivityMainBinding

    val loginbtn : Button = findViewById(R.id.loginButtonNavHeader)
    val addchannelbtn : ImageButton = findViewById(R.id.addChannelButton)
    val sendmessagebtn : ImageButton = findViewById(R.id.sendMessageBtn)

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)

        setSupportActionBar(binding.appBarMain.toolbar)

        loginbtn.setOnClickListener {
            val loginIntent = Intent(this, LoginActivity::class.java)
            startActivity(loginIntent)
        }
        val drawerLayout: DrawerLayout = binding.drawerLayout
        val navView: NavigationView = binding.navView
        val navController = findNavController(R.id.nav_host_fragment_content_main)
        appBarConfiguration = AppBarConfiguration(
            setOf(
                R.id.nav_home, R.id.nav_gallery, R.id.nav_slideshow
            ), drawerLayout
        )
        setupActionBarWithNavController(navController, appBarConfiguration)
    }
}

Logcat错误信息

Process: com.example.android.chatapplication, PID: 6449
    java.lang.RuntimeException: Unable to instantiate activity ComponentInfo{com.example.android.chatapplication/com.example.android.chatapplication.MainActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.pm.ApplicationInfo android.content.Context.getApplicationInfo()' on a null object reference
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3637)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3896)
        at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:85)
        at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:140)
        at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:100)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2326)
        at android.os.Handler.dispatchMessage(Handler.java:106)
        at android.os.Looper.loop(Looper.java:263)
        at android.app.ActivityThread.main(ActivityThread.java:8296)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:612)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1006)
     Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.pm.ApplicationInfo android.content.Context.getApplicationInfo()' on a null object reference
        at android.content.ContextWrapper.getApplicationInfo(ContextWrapper.java:183)
        at android.view.ContextThemeWrapper.getTheme(ContextThemeWrapper.java:174)
        at android.content.Context.obtainStyledAttributes(Context.java:744)
        at androidx.appcompat.app.AppCompatDelegateImpl.createSubDecor(AppCompatDelegateImpl.java:852)
        at androidx.appcompat.app.AppCompatDelegateImpl.ensureSubDecor(AppCompatDelegateImpl.java:819)
        at androidx.appcompat.app.AppCompatDelegateImpl.findViewById(AppCompatDelegateImpl.java:640)
        at androidx.appcompat.app.AppCompatActivity.findViewById(AppCompatActivity.java:261)
        at com.example.android.chatapplication.MainActivity.<init>(MainActivity.kt:25)
        at java.lang.Class.newInstance(Native Method)
        at android.app.AppComponentFactory.instantiateActivity(AppComponentFactory.java:95)
        at androidx.core.app.CoreComponentFactory.instantiateActivity(CoreComponentFactory.java:45)
        at android.app.Instrumentation.newActivity(Instrumentation.java:1254)
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3625)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3896) 
        at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:85) 
        at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:140) 
        at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:100) 
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2326) 
        at android.os.Handler.dispatchMessage(Handler.java:106) 
        at android.os.Looper.loop(Looper.java:263) 
        at android.app.ActivityThread.main(ActivityThread.java:8296) 
        at java.lang.reflect.Method.invoke(Native Method) 
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:612) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1006) 

正常运行的代码

fun loginbtnclicked(view : View ){
    val loginIntent = Intent(this, LoginActivity::class.java)
    startActivity(loginIntent)
}

问题分析

崩溃的核心原因是在Activity实例初始化阶段(成员变量声明时)调用了findViewById:

  • 类成员变量loginbtn直接在类中通过findViewById赋值,这会在Activity实例创建时(onCreate执行前)执行,此时Activity的Context还未初始化,布局也未加载,findViewById依赖的上下文环境不存在,直接触发空指针异常。
  • 而XML绑定的android:onClick="loginbtnclicked"方法,只会在用户点击按钮时才会被调用,此时Activity已经完成初始化和布局加载,Context正常可用,因此不会崩溃。

解决方案

方案1:延迟初始化控件,在onCreate中赋值

将控件声明改为lateinit,在setContentView之后再初始化控件:

class MainActivity : AppCompatActivity() {

    private lateinit var appBarConfiguration: AppBarConfiguration
    private lateinit var binding: ActivityMainBinding

    private lateinit var loginbtn: Button
    private lateinit var addchannelbtn: ImageButton
    private lateinit var sendmessagebtn: ImageButton

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)

        // 初始化控件
        loginbtn = findViewById(R.id.loginButtonNavHeader)
        addchannelbtn = findViewById(R.id.addChannelButton)
        sendmessagebtn = findViewById(R.id.sendMessageBtn)

        setSupportActionBar(binding.appBarMain.toolbar)

        loginbtn.setOnClickListener {
            val loginIntent = Intent(this, LoginActivity::class.java)
            startActivity(loginIntent)
        }

        // 导航相关代码
        val drawerLayout: DrawerLayout = binding.drawerLayout
        val navView: NavigationView = binding.navView
        val navController = findNavController(R.id.nav_host_fragment_content_main)
        appBarConfiguration = AppBarConfiguration(
            setOf(
                R.id.nav_home, R.id.nav_gallery, R.id.nav_slideshow
            ), drawerLayout
        )
        setupActionBarWithNavController(navController, appBarConfiguration)
    }
}

方案2:使用ViewBinding直接获取控件

既然已经启用了ViewBinding,可直接通过binding对象获取控件,无需调用findViewById,更安全高效:

class MainActivity : AppCompatActivity() {

    private lateinit var appBarConfiguration: AppBarConfiguration
    private lateinit var binding: ActivityMainBinding

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)

        setSupportActionBar(binding.appBarMain.toolbar)

        // 获取导航头中的按钮
        val loginbtn = binding.navView.getHeaderView(0).findViewById<Button>(R.id.loginButtonNavHeader)
        loginbtn.setOnClickListener {
            val loginIntent = Intent(this, LoginActivity::class.java)
            startActivity(loginIntent)
        }

        // 其他控件可直接通过binding获取(示例)
        // val addchannelbtn = binding.appBarMain.addChannelButton
        // addchannelbtn.setOnClickListener { ... }

        // 导航相关代码
        val drawerLayout: DrawerLayout = binding.drawerLayout
        val navView: NavigationView = binding.navView
        val navController = findNavController(R.id.nav_host_fragment_content_main)
        appBarConfiguration = AppBarConfiguration(
            setOf(
                R.id.nav_home, R.id.nav_gallery, R.id.nav_slideshow
            ), drawerLayout
        )
        setupActionBarWithNavController(navController, appBarConfiguration)
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 00:40:36