마스터Q&A 안드로이드는 안드로이드 개발자들의 질문과 답변을 위한 지식 커뮤니티 사이트입니다. 안드로이드펍에서 운영하고 있습니다. [사용법, 운영진]

값이 전달이 되지 않습니다.

0 추천
public class AddDay implements DayViewDecorator {
    private FirebaseFirestore db;
    private String data;
    int Year;
    int Month;
    int Day;
    ArrayList<CalendarDay> dates;
    Calendar calendar;

    public AddDay() {
        db = FirebaseFirestore.getInstance();
        String dgKey = FirebaseAuth.getInstance().getCurrentUser().getUid()+"000";
        db.collection("DiaryGroupList").document(dgKey)
                .collection("diaryList").get()
                .addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
                    @Override
                    public void onComplete(@NonNull Task<QuerySnapshot> task) {
                        if (task.isSuccessful()) {
                            for (QueryDocumentSnapshot document : task.getResult()) {
                                //Toast.makeText(Calendar2.this,document.getData().get("date").toString(),Toast.LENGTH_LONG).show();
                                calendar = Calendar.getInstance();
                                dates = new ArrayList<>();
                                data = document.getData().get("date").toString();
                                Year= Integer.parseInt(data.substring(0,4));
                                Month= Integer.parseInt(data.substring(4,6));
                                Day= Integer.parseInt(data.substring(6));
                                calendar.set(Year,Month-1,Day);
                                CalendarDay day = CalendarDay.from(calendar);
                                dates.add(day);

                                //여기 있은땐 모든 정보 받아와짐
                                }
                            //여기서부터 처음것만
                            }
                        }
                    }
                );
    }

    @Override
    public boolean shouldDecorate(CalendarDay day) {
       return true;
    }

    @Override
    public void decorate(DayViewFacade view) {
        view.addSpan(new DotSpan(8, Color.RED));
    }

db에서 값을 받아와 dates라는 값 안에 Year에는 2020 Month에는 11 Day에는 29라는 값이 들어가 있는걸 Log.i를 사용하여 확인했습니다.

그런데 마지막에 decorate를 사용하기 위해서는 shouldDecorate라는 것이 true일때, 작동이 한다고 합니다.

저는 dates에 값이 있는 2020 11 29에서만 true가 되고싶은데, 위에서 받아온 dates라는 값을 어떻게 불러와서 그 값만 true가 되도록 해야하는지 모르겠습니다.

현재는 true 값으로 지정해 두어 달력의 모든 날에 dot이 찍혀있습니다..

이야이야 (160 포인트) 님이 2020년 12월 2일 질문

1개의 답변

0 추천
public class AddDay implements DayViewDecorator {
//생략
   private List<CalendarDay> calendarDays = new ArrayList<>();
     
    public AddDay() {
        //생략 
                    @Override
                    public void onComplete(@NonNull Task<QuerySnapshot> task) {
                        if (task.isSuccessful()) {
                             parseDocument( task.getResult())
                        }
                    }
                );
    }

    // task.getResultType 은  위의  task.getResult()에서 리턴되는 타입으로 바꾸세요.
    private void parseDocument(task.getResultType taskResult) {
        Calendar calendar = Calendar.getInstance();
        calendarDays.clear();

        try {
        for (QueryDocumentSnapshot document : taskResult) {
                collectCalendarDays(QueryDocumentSnapshot, calendar)
        }
        } catch (java.text.ParseException e) {
            // 요구사항에 맞게 사용자에 에러 메세지를 보여주거나 하는 등의 예외처리를 하세요. 그냥 무시하면 안됨
        }
    }

    private void collectCalendarDays(QueryDocumentSnapshot document, Calendar calendar) {
          //데이터가 많지 않다면 두번째 메소드 파라미터를 지우고 이 메소드 안에서 Calendar를 생성하셔도 될듯.
          //Calendar calendar = Calendar.getInstance(); 
          String dateString = document.getData().get("date").toString();
         
          java.util.Date date = DateUtils.parseDate(dateString);
          calendar.setTime(date);
          CalendarDay calendarDay = CalendarDay.from(calendar);
          calendarDays.add(calendarDay);
    }
 
    @Override
    public boolean shouldDecorate(CalendarDay calendarDay) {
       return DateUtils.containsSpecificDay(calendarDay)
    }
 
    @Override
    public void decorate(DayViewFacade view) {
        view.addSpan(new DotSpan(8, Color.RED));
    }

}

public class DateUtils {
    public static final Date parseDate(String dateString, String pattern) {
         SimpleDateFormat sdf = new SimpleDateFormat(pattern);
         return sdf.parse(dateString);
    }

    // CalendarDay의 equals와 hashCode를 오버라이드 한 경우
    public static boolean containsSpecificDay(List<CalendarDay> sourceDays, CalendarDay specificDay) {
       return sourceDays.contains(specificDay);
    }

    //  DateUtils에 calendarDayEquals 메소드를 추가한 경우.
    public static boolean containsSpecificDay(List<CalendarDay> sourceDays, CalendarDay specificDay) {
        for (CalendarDay calendarDay : sourceDays) {
               if (DateUtils.calendarDayEquals(specificDay)) {
                    return true;
               }
       }  
       return false;
    }

    // 방법1 - 유틸리티메소드를 이용 - CalendarDay 클래스를 수정할 수 없을 경우.
     public static boolean calendarDayEquals(CalendarDay specificDay) {
          //구현은 CalendarDay가 어떻게 생겼는지 모르기 때문에 님이 알아서 하시면 될 듯합니다.
    }
}

// 방법2 - CalendarDay를 님이 수정할 수 있을 경우 equals와 hashCode를 오버라이드. 이게 더 좋은 방법으로 보임.
public CalendarDay {
   @Override
   public boolean equals(CalendarDay another) {
          //구현은 CalendarDay가 어떻게 생겼는지 모르기 때문에 님이 알아서 하시면 될 듯합니다.
    } 

   @Override
   public int hashCode() {
      // equals를 오버라이드 하시면 이 메소드도 반드시 오버라이드 하셔야 합니다. 
      // 그래야 맵같은 데서 사용할 때,이상하게 동작하지 않습니다.
   }
}

대략적인 코드는 위처럼 될 것 같구요.  equals 로직과 관련해서는 Calenday 클래스에 대한 정보는 님만 아시는 내용이므로, 직접 구현하시면 됩니다. 아마 어렵지 않게 하실 수 있을 겁니다. 아마 년일월 비교일 때니까요. 단순년원일 비교라면 CalendarDay의 equals와 hashCode를 메소드를 오버라이드 하시면 될 듯합니다. 그리고 List<CalendarDay>에서 해당 CalendarDay의 비교는 자바8의 경우 stream API가 있습니다. 가능하면 이걸 사용하시는 게 좋습니다. 저는 코틀린만 사용하기 때문에 해당 코드는 자바로 짜려면 약간의 시간의 필요해서 넣지 않았습니다.

그리고 일을 수월하기 만들시려면 CalendarDay에 문자열이나 년월일을 받아서 CalendarDay를 객체를 생성하는 CalendarDay Factory함수나 비슷한 추가되거나 하면 좋을 것 같습니다.

public class CalendarDay {

    public static CalendarDay of(int year, int month, int date) {
         Calendar calendar = Calendar.getInstance();
         calendar.setYear(...);
         calendar.setMonth(...);
         calendar.setDate(...);
         return CalendarDay.from(calendar);
    }

    public static CalendarDay of(String dateString, String pattern) {
         Date date = DateUtils.parseDate(dateString, pattern);
         Calendar calendar = Calendar.getInstance().setTime(date);
         return CalendarDay.from(calendar);
    } 
}


// 2020 11 29 -> CalendarDay
public static final YYYY_MM_DD_BY_SPACE = "yyyy MM dd"
CalendarDay.of("2020 11 29", YYYY_MM_DD_BY_SPACE)

이러면 Activity에 있는 로직도 좀 더 깔끔해 질듯 합니다. 도움이 되시길.

spark (227,470 포인트) 님이 2020년 12월 2일 답변
spark님이 2020년 12월 2일 수정
...