textView_Date 가 문제인 거 같네요. 해당 뷰는 edit_box.xml에 존재하는데 이 뷰를 바인딩하는 건 액티비티에서 아랫처럼 하셨기 때문에, textView_Date가 널인 상태인 걸로 보입니다.
textView_Date = (TextView)findViewById(R.id.textView_date);
buttonInsert의 onClickLisetener 안에서 처럼 Dialog의 레이아웃에서 findViewById를 하셔야 해당 텍스트뷰가 null 이 되지 않을 것 같네요.
안전한 코드를 위해서는 textView_Date는 Dialog 범위 안에서 접근하시는게 좋습니다. 현재는 액티비티 레벨에서 접근하기 때문에 Dialog가 보이지 않는 경우에 textView_Date는 null 이 됩니다. 변수는 적절한 범위에 두고 사용하시는 게 좋아요. 현재와 같은 구조는 우리집에만 있어야 할 물건을 부모님 집에 두고 가져와서 사용하고 돌려놓는 식의 방식이라 좋지 않습니다. textView_Date는 우리집(Dialog) 안에서만 필요하기 때문에 Dialog 안으로 관련 코드를 다 옮기세요.
먼저 아랫처럼 Dialog에 있는 버튼의 클릭이벤트를 제거하세요. 이렇게 하시면 어쩔 수 없이 Dialog 가 액티비티에 접근해야 하게 됩니다. OnClickHandler 는 Dialog 안으로 위치시키세요.
<Button
android:id="@+id/button"
...
android:onClick="OnClickHandler" // <- 요기 제거
... />
// private TextView textView_Date; ==> 제거
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
...
// textView_Date = (TextView)findViewById(R.id.textView_date); => 제거.
...
buttonInsert.setOnClickListener(new View.OnClickListener() {
// 1. 화면 아래쪽에 있는 데이터 추가 버튼을 클릭하면
@Override
public void onClick(View v) {
showExpenseFormDialog(); // 더 적절한 메소드 이름을 사용하세요.
}
});
}
private void showExpenseFormDialog() {
AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
View view = LayoutInflater.from(MainActivity.this)
.inflate(R.layout.edit_box, null, false);
builder.setView(view);
final Button buttonSubmit = view.findViewById(R.id.button_dialog_submit);
final EditText editTextID = view.findViewById(R.id.edittext_dialog_id);
final EditText editTextKorean = view.findViewById(R.id.edittext_dialog_korean);
final EditText editTextEnglish = view.findViewById(R.id.edittext_dialog_english);
final TextView textView_Date = view.findViewById(R.id.textView_date); // => 추가
ButtonSubmit.setText("삽입");
//****** 추가
TimePickerDialog.OnTimeSetListener callbackMethod = (view1, hourOfDay, minute) -> textView_Date.setText(hourOfDay + "시" + minute + "분");
view.findViewById(R.id.button).setOnClickListener(button -> {
TimePickerDialog timePickerDialog = new TimePickerDialog(this, callbackMethod, 8, 10, true);
timePickerDialog.show();
});
//******
final AlertDialog dialog = builder.create();
buttonSubmit.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
// 4. 사용자가 입력한 내용을 가져와서
String strID = editTextID.getText().toString();
String strKorean = editTextKorean.getText().toString();
String strEnglish = editTextEnglish.getText().toString();
// 5. ArrayList에 추가하고
Dictionary dict = new Dictionary(strID, strEnglish ,strKorean );
mArrayList.add(0, dict); //첫번째 줄에 삽입됨
//mArrayList.add(dict); //마지막 줄에 삽입됨
// 6. 어댑터에서 RecyclerView에 반영하도록 합니다.
mAdapter.notifyItemInserted(0);
//mAdapter.notifyDataSetChanged();
dialog.dismiss();
}
});
dialog.show();
}
보시면 아시겠지만, 코드가 Dialog관련코드가 상당히 길어서 한군데에 다 몰아놓으면 코드를 읽기가 상당히 힘들어 집니다. 읽기 쉽게 작은 단위로 쪼개시거나 별도의 클래스로 만들어서 사용하시길 권장드려요. 작은 단위로 쪼개놓은 코드를 예로 들면,
private void showExpenseFormDialog() {
final AlertDialog dialog = createExpenseDialog();
dialog.show();
final EditText editTextID = dialog.findViewById(R.id.edittext_dialog_id);
final EditText editTextKorean = dialog.findViewById(R.id.edittext_dialog_korean);
final EditText editTextEnglish = dialog.findViewById(R.id.edittext_dialog_english);
final TextView textView_Date = dialog.findViewById(R.id.textView_date);
dialog.findViewById(R.id.button).setOnClickListener(v -> {
showTimePickerDialog(textView_Date);
});
final Button submitButton = dialog.findViewById(R.id.button_dialog_submit);
submitButton.setText("삽입");
submitButton.setOnClickListener(v -> {
submitExpense(editTextID.getText().toString(), editTextKorean.getText().toString(), editTextEnglish.getText().toString());
dialog.dismiss();
});
}
private void showTimePickerDialog(TextView textViewToDisplay) {
TimePickerDialog timePickerDialog = new TimePickerDialog(
this,
(view1, hourOfDay, minute) -> textViewToDisplay.setText(hourOfDay + "시" + minute + "분"),
8,
10,
true);
timePickerDialog.show();
}
// 화면은 비용입력 화면인데, 왜 사전에 단어 등록을 하고 계신지 이해가 가진 않지만, 일단 화면대로 Expense라는 이름을 붙였습니다.
private void submitExpense(String id, String korean, String english) {
Dictionary dict = new Dictionary(id, english, korean);
mArrayList.add(0, dict); //첫번째 줄에 삽입됨
mAdapter.notifyItemInserted(0);
}
private AlertDialog createExpenseDialog() {
AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
View view = LayoutInflater.from(MainActivity.this)
.inflate(R.layout.edit_box, null, false);
builder.setView(view);
return builder.create();
}
별도의 클래스로 두어서 Dialog 관련 코드를 옮기는 것이 더 좋긴 합니다만, 우선은 위처럼 간단하게 메소드를 기능별로 쪼개서 두시면 코드를 읽기가 더 편해지고 나중에 별도의 클래스로 옮길 때도 도움이 될 거라고 생각합니다.