如何修复Android Studio中ViewBinding引发的运行时崩溃问题
Android项目使用ViewBinding后启动崩溃的解决方法
问题描述
在Android Studio开发项目,原本运行正常,引入ViewBinding后,真机运行时应用立即崩溃。
运行时错误日志
2024-04-05 11:11:36.978 9368-9368 AndroidRuntime usap64 E FATAL EXCEPTION: main Process: com.example.login_act, PID: 9368 java.lang.RuntimeException: Unable to instantiate activity ComponentInfo{com.example.login_act/com.example.login_act.MainActivity}: java.lang.InstantiationException: java.lang.Class<com.example.login_act.MainActivity> cannot be instantiated at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3737) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:4022) at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:85) at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135) at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2336) at android.os.Handler.dispatchMessage(Handler.java:106) at android.os.Looper.loop(Looper.java:246) at android.app.ActivityThread.main(ActivityThread.java:8653) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:602) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1130) Caused by: java.lang.InstantiationException: java.lang.Class<com.example.login_act.MainActivity> cannot be instantiated at java.lang.Class.newInstance(Native Method) at android.app.AppComponentFactory.instantiateActivity(AppComponentFactory.java:95) at androidx.core.app.CoreComponentFactory.instantiateActivity(CoreComponentFactory.java:44) at android.app.Instrumentation.newActivity(Instrumentation.java:1253) at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3725) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:4022) at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:85) at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135) at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2336) at android.os.Handler.dispatchMessage(Handler.java:106) at android.os.Looper.loop(Looper.java:246) at android.app.ActivityThread.main(ActivityThread.java:8653) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:602) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1130) 2024-04-05 11:11:37.042 4589-4614 WindowManager system_server E win=Window{3a9cc03 u0 Splash Screen com.example.login_act EXITING} destroySurfaces: appStopped=false win.mWindowRemovalAllowed=true win.mRemoveOnExit=true win.mViewVisibility=0 caller=com.android.server.wm.ActivityRecord.destroySurfaces:5251 com.android.server.wm.ActivityRecord.destroySurfaces:5232 com.android.server.wm.WindowState.onExitAnimationDone:5654 com.android.server.wm.-$$Lambda$01bPtngJg5AqEoOWfW3rWfV7MH4.accept:2 java.util.ArrayList.forEach:1262 com.android.server.wm.ActivityRecord.onAnimationFinished:7162 com.android.server.wm.WindowContainer.doAnimationFinished:2626
原MainActivity.kt代码
abstract class MainActivity : AppCompatActivity() , View.OnClickListener { private lateinit var binding: ActivityMainBinding override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) binding = ActivityMainBinding.inflate(layoutInflater) setContentView(binding.root) val username = binding.usernameTxt val password = binding.passwordTxt val login_btn = binding.LoginBtn login_btn.setOnClickListener { } when{ TextUtils.isEmpty(username.text.toString()) ->{ Toast.makeText(applicationContext,"Please enter your username", Toast.LENGTH_SHORT).show() } TextUtils.isEmpty(password.text.toString()) ->{ Toast.makeText(applicationContext,"Pleas enter your password", Toast.LENGTH_SHORT).show() } username.toString() != "admin123" && password.toString() != "adminpass123" ->{ Toast.makeText(applicationContext,"Invalid Username and/or Password", Toast.LENGTH_SHORT).show() } else ->{ Toast.makeText(applicationContext,"Logging in....", Toast.LENGTH_SHORT).show() } } } }
原activity_main.xml布局
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout 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" android:background="@drawable/gradient_bg" tools:context=".MainActivity"> <ImageView android:id="@+id/imageView" android:layout_width="199dp" android:layout_height="244dp" android:layout_marginTop="44dp" android:backgroundTint="#2E2727" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" app:srcCompat="@drawable/avatar" /> <EditText android:id="@+id/username_Txt" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginStart="20dp" android:layout_marginTop="40dp" android:layout_marginEnd="20dp" android:backgroundTint="#100A0A" android:ems="10" android:hint="@string/username" android:inputType="text" android:minHeight="48dp" android:textColor="#000000" android:textColorHint="#0B0909" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintHorizontal_bias="0.497" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/imageView" /> <EditText android:id="@+id/password_Txt" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginStart="20dp" android:layout_marginTop="40dp" android:layout_marginEnd="20dp" android:backgroundTint="#050505" android:ems="10" android:hint="@string/password" android:inputType="textPassword" android:minHeight="48dp" android:textColor="#000000" android:textColorHint="#0B0909" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/username_Txt" /> <Button android:id="@+id/LoginBtn" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginStart="20dp" android:layout_marginTop="40dp" android:layout_marginEnd="20dp" android:backgroundTint="#DAD8D8" android:text="@string/Login_btn" android:textColor="#000000" android:textSize="20sp" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/password_Txt" /> <TextView android:id="@+id/textView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="20dp" android:layout_marginTop="10dp" android:layout_marginEnd="20dp" android:text="@string/forgot_pass" android:textColor="#000000" android:textColorHint="#020202" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/LoginBtn" /> </androidx.constraintlayout.widget.ConstraintLayout>
问题分析与解决
1. 核心崩溃原因:Activity被声明为抽象类
日志中InstantiationException明确表明系统无法实例化MainActivity,因为你将它声明为abstract(抽象类)。Android系统需要通过反射创建Activity实例,而抽象类不能被实例化,这是导致崩溃的直接原因。
解决: 去掉MainActivity的abstract修饰符,将类声明改为:
class MainActivity : AppCompatActivity(), View.OnClickListener {
2. ViewBinding变量名错误
布局中按钮的id是LoginBtn,ViewBinding会自动将其转换为小驼峰命名loginBtn,原代码中binding.LoginBtn会导致编译错误,需修正为binding.loginBtn。
3. 逻辑位置错误
原代码中when判断逻辑直接写在onCreate方法里,会在Activity启动时立即执行,而非点击登录按钮时触发。需要将这部分逻辑移到按钮的点击监听内部。
4. 文本判断错误
原代码中username.toString()获取的是EditText对象的字符串表示,而非输入框内的文本内容,需改为username.text.toString(),password同理。
修正后的MainActivity.kt代码
class MainActivity : AppCompatActivity(), View.OnClickListener { private lateinit var binding: ActivityMainBinding override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) binding = ActivityMainBinding.inflate(layoutInflater) setContentView(binding.root) val username = binding.usernameTxt val password = binding.passwordTxt val loginBtn = binding.loginBtn loginBtn.setOnClickListener { when { TextUtils.isEmpty(username.text.toString().trim()) -> { Toast.makeText(applicationContext, "请输入用户名", Toast.LENGTH_SHORT).show() } TextUtils.isEmpty(password.text.toString().trim()) -> { Toast.makeText(applicationContext, "请输入密码", Toast.LENGTH_SHORT).show() } username.text.toString() != "admin123" || password.text.toString() != "adminpass123" -> { Toast.makeText(applicationContext, "用户名或密码错误", Toast.LENGTH_SHORT).show() } else -> { Toast.makeText(applicationContext, "正在登录...", Toast.LENGTH_SHORT).show() } } } } override fun onClick(v: View?) { // 实现接口方法,若不需要可留空或根据需求添加逻辑 } }
注:还修正了判断条件的逻辑错误(将
&&改为||,因为只要用户名或密码其中一个错误就应该提示),并添加了trim()去除输入的首尾空格,提升用户体验。
内容的提问来源于stack exchange,提问作者EJ Lin
相关产品推荐
相关产品推荐

