點擊「我同意」CheckBox 啟用按鈕,再點擊按鈕時應用崩潰,Logcat 提示:
java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.TextView.setText(java.lang.CharSequence)' on a null object reference
at com.ample.receive.MainActivity.onClick(MainActivity.java:45)
代碼中聲明了 myTextView1、myTextView2 但未在 onCreate 中調用 findViewById 綁定布局控件,導致它們為 null,調用 setText 時拋出 NPE。
private TextView myTextView1;
private TextView myTextView2;
@Override
protected void onCreate(Bundle savedInstanceState) {
// ...
myCheckBox = findViewById(R.id.myCheckBox);
myButton = findViewById(R.id.myButton);
// 缺失:myTextView1 = findViewById(R.id.myTextView1);
// 缺失:myTextView2 = findViewById(R.id.myTextView2);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
myCheckBox = findViewById(R.id.myCheckBox);
myButton = findViewById(R.id.myButton);
myTextView1 = findViewById(R.id.myTextView1); // 新增
myTextView2 = findViewById(R.id.myTextView2); // 新增
myCheckBox.setOnClickListener(this);
myButton.setOnClickListener(this);
}
build.gradle 啟用 viewBinding true,自動生成綁定類,消除 findViewById 與 NPE。
// Activity 中
private ActivityMainBinding binding;
@Override
protected void onCreate(Bundle savedInstanceState) {
binding = ActivityMainBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
binding.myCheckBox.setOnClickListener(...);
binding.myTextView1.setText(...); // 直接訪問,編譯期檢查非空
}
apply plugin: 'kotlin-android-extensions' 可直接用 ID 訪問 View。findViewById 集中在 initViews() 中,便於檢查遺漏。onCreate 結束處,觀察 View 變量是否為 null。Android 開發中 90% 的 NPE 來自未初始化的 View。養成「聲明即綁定」習慣,或遷移至 ViewBinding,可徹底杜絕此類低級崩潰。