2021.10.06.수요일 개발 일지

5673 단어 flutterflutter

개발 중인 앱 PEEP은 사용자의 감정에 따라 음악을 추천하여 재생해준다. 감정은 총 5가지로, HAPPY, SAD, ANGRY, CALM, FEAR이다.

어제의 개발은...

문제 상황

music_player_page.dart는 음악 플레이어 화면이고 노래의 느낌에 맞게 분류된 감정에 따라 배경 색이 달라진다.

music_player_page.dart에서 아래와 같이 감정에 대한 색이 하드코딩 되어 있다.

var pageColor = Colors.white;
if (randomEmotion == 'happy') {
  pageColor = const Color(0xFFd5b15c);
} else if (randomEmotion == 'sad') {
  pageColor = const Color(0xFF7fbad0);
} else if (randomEmotion == 'angry') {
  pageColor = const Color(0xFFd77881);
} else if (randomEmotion == 'calm') {
  pageColor = const Color(0xFF669f82);
} else if (randomEmotion == 'fear') {
  pageColor = const Color(0xFF8481ac);
}

또한, 같은 화면에서 파도 물결이 넘실거리는 애니메이션이 있는데 이 또한 감정색과 어울리는 비슷한 색이며 위의 코드와 Color()의 HEX 값의 차이만 있다.

if (randomEmotion == 'happy') {
  pickColor = const Color(0xFFe8c075);
  pickColor1 = const Color(0xFFd57a47);
} else if (randomEmotion == 'sad') {
  pickColor = const Color(0xFFa5c3d7);
  pickColor1 = const Color(0xFF446199);
} else if (randomEmotion == 'angry') {
  pickColor = const Color(0xFFd77d92);
  pickColor1 = const Color(0xFFcc4e60);
} else if (randomEmotion == 'calm') {
  pickColor = const Color(0xFF57a481);
  pickColor1 = const Color(0xFF426641);
} else if (randomEmotion == 'fear') {
  pickColor = const Color(0xFF8776a4);
  pickColor1 = const Color(0xFF564986);
}

내가 느낀 이 코드의 문제점과 방향성은 아래와 같다.

  • 같은 역할을 하는 코드의 중복
  • music_player_page.dart의 주요 목적은 플레이어 화면을 보여주는 것인데, 특정 위젯의 디테일한 설정이 이 파일 안에 드러나 있어 파일의 목적과는 다소 거리감 있어보임
  • 음악 플레이어는 홈 화면에서도 하단바로 보이고 하단바의 색 또한 노래의 감정에 따라 색이 변화한다. 그렇기에 위와 같은 코딩은 다른 소스 코드 파일에서도 중복될 수 있다. 또, 현재 재생 곡 변경 시 바뀌어야 한다. 따라서 노래의 감정과 해당 색은 다른 파일에서도 공유되어야 한다.

해결 방법은 아래와 같다.

  • 노래의 감정과 색은 다른 파일에서도 공유해야하고 앱의 특성상 다양한 소스 코드 파일에서 공유할 가능성이 높기 때문에 글로벌하게 쓰일 수 있도록 코드를 별도 파일로 분리한다.

개선 결과

globals.dart

감정의 색을 분리한 소스 코드 파일이다.

class EmotionColor {
  static const HAPPY    = "HAPPY";
  static const SAD      = "SAD";
  static const ANGRY    = "ANGRY";
  static const CALM     = "CALM";
  static const FEAR     = "FEAR";
  static const DEFAULT  = "DEFAULT";

  static const _normalColorMap = {
    HAPPY:    const Color(0xFFd5b15c),
    SAD:      const Color(0xFF7fbad0),
    ANGRY:    const Color(0xFFd77881),
    CALM:     const Color(0xFF669f82),
    FEAR:     const Color(0xFF8481ac),
    DEFAULT:  Colors.white,
  };

  static const _lightColorMap = {
    HAPPY:    const Color(0xFFe8c075),
    SAD:      const Color(0xFFa5c3d7),
    ANGRY:    const Color(0xFFd77d92),
    CALM:     const Color(0xFF57a481),
    FEAR:     const Color(0xFF8776a4),
    DEFAULT:  Colors.white,
  };

  static const _darkColorMap = {
    HAPPY:    const Color(0xFFd57a47),
    SAD:      const Color(0xFF446199),
    ANGRY:    const Color(0xFFcc4e60),
    CALM:     const Color(0xFF426641),
    FEAR:     const Color(0xFF564986),
    DEFAULT:  Colors.white,
  };

  const EmotionColor._();

  static getNormalColorFor(String emotion) => _normalColorMap[emotion.toUpperCase()] ?? _normalColorMap[DEFAULT];
  static getLightColorFor(String emotion) => _lightColorMap[emotion.toUpperCase()] ?? _lightColorMap[DEFAULT];
  static getDarkColorFor(String emotion) => _darkColorMap[emotion.toUpperCase()] ?? _darkColorMap[DEFAULT];
}
  • 감정 종류를 문자열로 선언하고 함수 호출 시 입력받도록 하였다.
  • 사용하는 색의 종류를 normal, light, dark로 나누어 선언하여 물결색에 쓰이는 색도 모두 포함하였다.

호출 부분

if (randomEmotion == null || randomEmotion == "") {
  randomEmotion = "default";
}

EmotionColor.getNormalColorFor(randomEmotion),

randomEmotion이라는 변수에 감정 종류를 문자열로 입력받고 함수를 호출하여 매개변수로 넘긴다.

개선할 점

깃허브 커밋 결과 링크

  • 현재 재생되는 감정의 색이 변경되었을 때, 플레이어 화면에서 드롭다운 부분 UI의 색상의 변경이 바로 적용되지 않음.

  • 그래서 InheritedWidget를 이용해 변수가 변경되었을 때 UI에도 바로 적용될 수 있도록 하는 것이 필요해보여 클래스를 생성하였으나, 기본값 설정이 안돼서 에러가 남. 기본값 설정 방법을 찾는 중이다.
class CurrentEmotion extends InheritedWidget {
  const CurrentEmotion({
    Key key,
    this.emotion,
    Widget child,
  }) : super(key: key, child: child);

  final String emotion;

  static CurrentEmotion of(BuildContext context) {
    final CurrentEmotion result = context.dependOnInheritedWidgetOfExactType<CurrentEmotion>();
    assert(result != null, 'No CurrentEmotion found in context');
    return result;
  }

  @override
  bool updateShouldNotify(CurrentEmotion old) => emotion != old.emotion;
}

도움 된 링크

좋은 웹페이지 즐겨찾기