두 기능 모두 사용자로부터 날짜, 시간을 입력받고, 데이터를 TextView 에 업데이트하는 것은 공통이다.
하지만 DatePicker 는 TextView 에 업데이트하고, TimePicker 는 ViewModel 에 업데이트 하는 차이가 있다.
private fun showDatePicker(textView: TextView) {
val datePickerDialog = DatePickerDialog(this, null, viewModel.year, viewModel.month, viewModel.day)
// datePickerDialog 의 header 숨김 (custom)
datePickerDialog.datePicker.findViewById<View>(resources.getIdentifier("date_picker_header", "id", "android"))?.visibility = View.GONE
// DatePickerDialog 에서 날짜 선택 시 호출되는 콜백 설정
datePickerDialog.datePicker.init(viewModel.year, viewModel.month, viewModel.day) { view, year, monthOfYear, dayOfMonth ->
// 선택된 날짜를 tv 에 반영
textView.text = "${monthOfYear + 1}월 ${dayOfMonth}일"
datePickerDialog.dismiss()
}
datePickerDialog.show()
}
private fun showCustomTimePicker(isStartTime: Boolean) {
val customTimePickerView = layoutInflater.inflate(R.layout.custom_time_picker, null)
// View 참조
val timePicker = customTimePickerView.findViewById<TimePicker>(R.id.time_picker)
val setButton = customTimePickerView.findViewById<Button>(R.id.time_btn_yes)
val dialog = AlertDialog.Builder(this)
.setView(customTimePickerView)
.create()
// "set" 버튼 클릭 시 시간 설정 후 닫기
setButton.setOnClickListener {
val hour = timePicker.hour
val minute = timePicker.minute
if (isStartTime) {
viewModel.setStartTime(hour, minute)
} else {
viewModel.setEndTime(hour, minute)
}
dialog.dismiss()
}
dialog.show()
}
시간 업데이트 방식이 MVVM 패턴에 더 가깝다. ViewModel을 통해 UI 데이터를 관리하기 때문에, ViewModel 내 데이터가 변경되면 자동으로 UI가 업데이트되는 구조이므로, 데이터의 일관성이 보장된다.
날짜 업데이트 방식은 ViewModel 과의 직접적인 상호작용 없이 TextView를 업데이트한다.
이 방식은 ViewModel의 상태를 반영하지 않기 때문에, 데이터가 분산될 위험이 있다.
종합적으로, MVVM 아키텍처를 따르는 앱에서는 시간 업데이트 방식이 더 권장된다. 이는 앱의 다른 부분과의 일관성을 유지하고, 데이터를 중앙에서 관리할 수 있게 해 주기 때문입니다.
그러나 필자는, 사용자가 UI에서 직접적으로 날짜를 변경하는 간단한 작업이므로, 이 방식이 더 직관적이라고 판단했다. 기능을 확장하는 과정에서 일관성을 유지해야한다고 판단되면 날짜 선택 함수도 ViewModel 을 통해 업데이트 하는 방식으로 변경할 예정이다.
private void showDatePicker(final TextView textView) {
DatePickerDialog datePickerDialog = new DatePickerDialog(this, null, viewModel.getYear(), viewModel.getMonth(), viewModel.getDay());
// Hide the date picker header
View headerView = datePickerDialog.getDatePicker().findViewById(Resources.getSystem().getIdentifier("date_picker_header", "id", "android"));
if (headerView != null) {
headerView.setVisibility(View.GONE);
}
// Set the date selection callback
datePickerDialog.getDatePicker().init(viewModel.getYear(), viewModel.getMonth(), viewModel.getDay(), new DatePicker.OnDateChangedListener() {
@Override
public void onDateChanged(DatePicker view, int year, int monthOfYear, int dayOfMonth) {
String date = (monthOfYear + 1) + "월 " + dayOfMonth + "일";
textView.setText(date);
datePickerDialog.dismiss();
}
});
datePickerDialog.show();
}
private void showCustomTimePicker(final boolean isStartTime) {
View customTimePickerView = LayoutInflater.from(this).inflate(R.layout.custom_time_picker, null);
final TimePicker timePicker = customTimePickerView.findViewById(R.id.time_picker);
Button setButton = customTimePickerView.findViewById(R.id.time_btn_yes);
final AlertDialog dialog = new AlertDialog.Builder(this)
.setView(customTimePickerView)
.create();
setButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
int hour = timePicker.getCurrentHour();
int minute = timePicker.getCurrentMinute();
if (isStartTime) {
viewModel.setStartTime(hour, minute);
} else {
viewModel.setEndTime(hour, minute);
}
dialog.dismiss();
}
});
dialog.show();
}