[Android] viewModel 데이터를 View 로 전달하기(Java/Kotlin)

이도연·2024년 3월 27일
0

android studio

목록 보기
28/28
post-thumbnail

기능

android 에서 기본으로 제공하는 DatePicker 와 TimePicker 로 날짜와 시간을 선택하면 text view 로 업데이트 되는 형식이다.


진행 방식

두 기능 모두 사용자로부터 날짜, 시간을 입력받고, 데이터를 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()
    }

날짜 업데이트 방식

  1. 사용자가 날짜를 선택하면
  2. DatePickerDialog의 init 메서드에서 콜백이 호출된다.(직접 TextView 업데이트)
  3. viewModel 에는 변경된 날짜에 관한 언급이 없다. 즉, ViewModel 내부의 데이터가 이 함수를 통해 직접 업데이트되지는 않는다.

시간 업데이트 방식

  1. 사용자가 시간을 선택하고 "set" 버튼을 클릭하면
  2. 클릭 리스너에서 viewModel의 setStartTime 또는 setEndTime 을 호출한다. (LiveData 값 업데이트)
  3. Activity는 viewModel의 startTime 또는 endTime LiveData 객체의 변화를 관찰하고 있다. 값이 변경되면 Observer가 이를 감지하고 관련 TextView에 새로운 시간을 반영한다.

어느 방식이 더 효율적인가

시간 업데이트 방식이 MVVM 패턴에 더 가깝다. ViewModel을 통해 UI 데이터를 관리하기 때문에, ViewModel 내 데이터가 변경되면 자동으로 UI가 업데이트되는 구조이므로, 데이터의 일관성이 보장된다.

날짜 업데이트 방식은 ViewModel 과의 직접적인 상호작용 없이 TextView를 업데이트한다.
이 방식은 ViewModel의 상태를 반영하지 않기 때문에, 데이터가 분산될 위험이 있다.


결론

종합적으로, MVVM 아키텍처를 따르는 앱에서는 시간 업데이트 방식이 더 권장된다. 이는 앱의 다른 부분과의 일관성을 유지하고, 데이터를 중앙에서 관리할 수 있게 해 주기 때문입니다.

그러나 필자는, 사용자가 UI에서 직접적으로 날짜를 변경하는 간단한 작업이므로, 이 방식이 더 직관적이라고 판단했다. 기능을 확장하는 과정에서 일관성을 유지해야한다고 판단되면 날짜 선택 함수도 ViewModel 을 통해 업데이트 하는 방식으로 변경할 예정이다.



Java

날짜 업데이트 함수

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();
    }


0개의 댓글