Android Dialog按钮触发NullPointerException问题求助
我需要更新ListAdapter中的数据,为此做了一个包含2个EditText和1个Button的Dialog,但点击Dialog里的“更新”按钮时抛出android.view.View$OnClickListener' on a null object reference异常,我用Firebase实时数据库存储数据。
堆栈信息
java.lang.NullPointerException: Attempt to invoke virtual method 'void
android.widget.Button.setOnClickListener(android.view.View$OnClickListener)'
on a null object reference
at
com.example.notasderober.ReadNotes.showUpdateDialog(ReadNotes.java:106)
at com.example.notasderober.ReadNotes.access$000(ReadNotes.java:33)
at
com.example.notasderober.ReadNotes$2.onItemClick(ReadNotes.java:77)
at android.widget.AdapterView.performItemClick(AdapterView.java:330)
at android.widget.AbsListView.performItemClick(AbsListView.java:1187)
at android.widget.AbsListView$PerformClick.run(AbsListView.java:3179)
at android.widget.AbsListView$3.run(AbsListView.java:4097)
at android.os.Handler.handleCallback(Handler.java:938)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:223)
at android.app.ActivityThread.main(ActivityThread.java:7656)
at java.lang.reflect.Method.invoke(Native Method)
at
com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
at android.os.ZygoteInit.main(ZygoteInit.java:947)
相关代码
Java代码
package com.example.notasderober; import androidx.annotation.NonNull; import androidx.appcompat.app.AlertDialog; import androidx.appcompat.app.AppCompatActivity; import android.os.Bundle; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.widget.AdapterView; import android.widget.Button; import android.widget.EditText; import android.widget.ListView; import android.widget.Toast; import com.google.firebase.database.DataSnapshot; import com.google.firebase.database.DatabaseError; import com.google.firebase.database.DatabaseReference; import com.google.firebase.database.FirebaseDatabase; import com.google.firebase.database.ValueEventListener; import java.util.ArrayList; import java.util.List; public class ReadNotes extends AppCompatActivity { List<Users> notesList; ListView listView; DatabaseReference studentDbRef; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_read_notes); listView = findViewById(R.id.listview); notesList = new ArrayList<>(); studentDbRef = FirebaseDatabase.getInstance().getReference("Notas"); studentDbRef.addValueEventListener(new ValueEventListener() { @Override public void onDataChange(@NonNull DataSnapshot snapshot) { notesList.clear(); for (DataSnapshot studentDatasnap : snapshot.getChildren()){ Users notes = studentDatasnap.getValue(Users.class); notesList.add(notes); } ListAdapter adapter = new ListAdapter(ReadNotes.this,notesList); listView.setAdapter(adapter); } @Override public void onCancelled(@NonNull DatabaseError error) { } }); listView.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) { Users students = notesList.get(i); showUpdateDialog(students.getId(), students.getName()); } }); } //SHOW UPDATE DIALOG private void showUpdateDialog (final String id, String name) { Log.d("updateDialog","Dialog update"); final AlertDialog.Builder updateDialog = new AlertDialog.Builder(this); updateDialog.setView(updateDialogView); final EditText updateNote = findViewById(R.id.updateNoteText); final EditText updateNoteContent = findViewById(R.id.updateContentText); updateDialog.setTitle("Actualizando : " + name); final AlertDialog alertDialog = updateDialog.create(); alertDialog.show(); updateButton.setOnClickListener(new View.OnClickListener() { // maybe here is the problem @Override public void onClick(View view) { String noteTitle = updateNote.getText().toString(); String noteContent = updateNoteContent.getText().toString(); updateData(id,noteTitle,noteContent); Toast.makeText(ReadNotes.this,"Nota actualizada",Toast.LENGTH_SHORT).show(); } }); } //UPDATE DATA IN DATABASE private void updateData (String id, String name, String note) { DatabaseReference dbRef = FirebaseDatabase.getInstance().getReference("Notas").child(id); Users noteEx = new Users(id,name,note); dbRef.setValue(noteEx); } }
主布局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" tools:context=".ReadNotes"> <TextView android:id="@+id/textView5" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Saved notes" android:textSize="34sp" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintHorizontal_bias="0.497" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintVertical_bias="0.023" /> <ListView android:id="@+id/listview" android:layout_width="409dp" android:layout_height="668dp" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintVertical_bias="0.968" /> </androidx.constraintlayout.widget.ConstraintLayout>
Dialog布局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"> <EditText android:id="@+id/updateNoteText" android:layout_width="289dp" android:layout_height="144dp" android:ems="10" android:hint="Nota" android:inputType="text" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintHorizontal_bias="0.368" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintVertical_bias="0.054" /> <EditText android:id="@+id/updateContentText" android:layout_width="286dp" android:layout_height="127dp" android:ems="10" android:hint="Contenido nota" android:inputType="text" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintHorizontal_bias="0.381" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintVertical_bias="0.462" /> <Button android:id="@+id/updateNoteButton" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Modificar" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintVertical_bias="0.976" /> </androidx.constraintlayout.widget.ConstraintLayout>
错误原因与修复方案
错误原因
- Dialog视图提前初始化失效:在
onCreate中提前加载的updateDialogView没有和后续创建的AlertDialog绑定,导致按钮引用为空。 - 控件查找范围错误:直接用
findViewById获取Dialog中的EditText,而不是从Dialog视图内部查找,会找不到目标控件(因为EditText属于Dialog布局,不在Activity主布局中)。
修复后的showUpdateDialog方法
private void showUpdateDialog (final String id, String name) { Log.d("updateDialog","Dialog update"); final AlertDialog.Builder updateDialog = new AlertDialog.Builder(this); // 每次创建Dialog时重新加载布局 LayoutInflater inflater = getLayoutInflater(); View updateDialogView = inflater.inflate(R.layout.update_dialog,null); updateDialog.setView(updateDialogView); // 从Dialog视图内部获取控件 final EditText updateNote = updateDialogView.findViewById(R.id.updateNoteText); final EditText updateNoteContent = updateDialogView.findViewById(R.id.updateContentText); Button updateButton = updateDialogView.findViewById(R.id.updateNoteButton); // 填充原有数据到输入框(可选优化) updateNote.setText(name); updateDialog.setTitle("Actualizando : " + name); final AlertDialog alertDialog = updateDialog.create(); alertDialog.show(); updateButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { String noteTitle = updateNote.getText().toString(); String noteContent = updateNoteContent.getText().toString(); updateData(id,noteTitle,noteContent); Toast.makeText(ReadNotes.this,"Nota actualizada",Toast.LENGTH_SHORT).show(); alertDialog.dismiss(); // 更新后关闭Dialog } }); }
额外清理工作
删除类中多余的成员变量:
Button updateButton; View updateDialogView; LayoutInflater inflater;
同时删除onCreate中提前加载Dialog布局的代码:
inflater = getLayoutInflater(); updateDialogView = inflater.inflate(R.layout.update_dialog,null); updateButton = updateDialogView.findViewById(R.id.updateNoteButton);
内容的提问来源于stack exchange,提问作者Rober

