Skip to content

날씨 관련해서 로컬, 원격 데이터 받아오거나 갱신 시점, UI표시 등등

KimDonghyeok edited this page May 29, 2024 · 1 revision

서론 (문제인식)

날씨 데이터를 오늘과 어제의 데이터만 받아온것으로 인해 2가지의 문제가 생겼다.

기존에는 시간별 일기예보를 당일에 해당되는 24시간의 정보를 보여주었다. 하지만 사용자의 현재 시간을 기준으로 이후 24시간의 시간별 일기예보를 보여주는 것으로 기획이 변경되어 데이터 단의 수정이 필요했다. 기획이 변경 됨에 따라 어제와 오늘의 날씨 정보 뿐 아니라 현재 시간이 자정에 가까울 경우, 그 다음날의 날씨 정보도 불러올 필요가 있었다. 그런데 기존 데이터 갱신 로직은 3시간 간격으로 새로운 정보를 호출하도록 되어있었기 때문에 이 데이터를 갱신하는 로직과 UI를 변경하게 되었다. 또한 다음날 00시 일 경우 ‘내일’로 표기되도록 구현하였다.

구현


레포지토리

데이터 호출 시, 로컬에 있는 데이터가 현재 날짜와 같지 않으면 새롭게 데이터를 불러오도록 조건 추가

/// Repository
/// 로컬 데이터가 없거나 만료된 데이터인지, 갱신 시점이 오늘이 맞는지 확인한다.
/// localData.createdAt.day != now.day 오늘 갱신한 데이터인지 확인하는 조건 추가
bool _isOldDataOrExpired(DailyLocationWeather? localData) {
  final now = DateTime.now();
  return (localData == null ||
      localData.createdAt.day != now.day ||
      localData.createdAt.isBefore(now.subtract(const Duration(hours: 3))));
}

뷰 모델

현재시간 기준으로 이후 24시간의 일기예보를 가져오도록 함

/// ViewModel
/// 현재 시간부터 24시간 이후까지의 날씨 정보를 가져오기
Future<void> _getWeatherByTimeList() async {
  DateTime now = DateTime.now();
  int currentHour = now.hour;
  List<Weather> weatherList = [];

  // 현재 시간 이후의 날씨 정보 목록
  List<Weather> weatherAfterCurrentTime = dailyLocationWeather!.weatherList
      .where((e) => e.timeTemperature.hour >= currentHour)
      .toList();

  // 중복되는 시간의 정보를 기록합니다.
  Set<int> hoursAlreadyAdded =
      Set.from(weatherAfterCurrentTime.map((e) => e.timeTemperature.hour));

  // 현재 시간 이후의 객체를 추가합니다.
  weatherList.addAll(weatherAfterCurrentTime);

  // 남은 시간만큼을 dailyLocationWeather!.tomorrowWeatherList에서 가져와서 채웁니다.
  int remainingCount = 24 - weatherAfterCurrentTime.length;

  if (remainingCount > 0) {
    List<Weather> tomorrowWeather = dailyLocationWeather!.tomorrowWeatherList
        .where((e) => !hoursAlreadyAdded.contains(e.timeTemperature.hour))
        .take(remainingCount)
        .toList();

    weatherList.addAll(tomorrowWeather);
  }
  _weatherByTimeList = weatherList;
}

오전 00시 일 경우 '내일' 로 표기

/// 시간별 일기예보 위젯
/// 오전 00시 일 경우 '내일' 로 표기되도록 하였다.
@override
Widget build(BuildContext context) {
  String time = DateFormat('aa HH시', 'ko_KR')
      .format(weatherList![index].timeTemperature);

  return Padding(
    padding: const EdgeInsets.symmetric(vertical: 12, horizontal: 10),
    child: Column(
      crossAxisAlignment: CrossAxisAlignment.center,
      children: [
        SizedBox(
          child: Text(       
            time == '오전 00시' ? '내일' : time,
            textAlign: TextAlign.center,
            style: const TextStyle(
              fontSize: 13,
              color: Colors.white,
            ),
          ),
        ),
        ...
      ],
    ),
  );
}

결론 (느낀점)

  • 기획 단계에서 화면의 세부적인 동작의 엣지 케이스 또한 고려해야 한다는 것을 깨달았다.