Flutter + Firebaseでモバイルアプリを作った時にColorの保存で困った話


はじめに

1ヶ月ほど前に、Flutterに手を出しました。
YouTubeに上がっているチュートリアルをやって、それからオリジナルのアプリを作り始めたんですが躓きまくり。
アプリを作るにあたって、ほとんど触ったことなかったFirebaseのサービスもいろいろ使ってみました。

  • Firebase Authentication
  • Cloud Firestore
  • Cloud Storage for Firebase
  • Firebase Cloud Messaging
  • Cloud Functions for Firebase

いやぁ便利ですね。僕が作ってるぐらいのアプリならFirebaseで全部できちゃうじゃん。
ところが問題が起きました。

問題

「Colorが保存できない...」

Cloud Firestoreが対応しているデータ型は

  • string
  • number
  • boolean
  • map
  • array
  • null
  • timestamp
  • geopoint
  • reference

の9つ。
mapもarrayもこの9つの型しか保存できません。

よわよわな僕は困りました。

「どうやって保存しよう...」

「Stringで保存するしかないかぁ」

結局どうしたか

Stringで保存することにしました。

いろいろ調べてみて、「Colorのhex値だけ取り出してそれをStringで保存、取ってきたhex値を使ってColorに戻す」っていう方法がなんかいい感じだったんですが、僕の場合、保存したいのはMaterialColor(なんか名前がついてる色)だったので、ちょっと違うことをしてみました。

コード

// Colorの値をStringに変換
String stringifyColor(Color pickedColor) {
  String stringifiedColor;

  switch (pickedColor) {
    case Colors.pink:
      stringifiedColor = 'pink';
      break;
    case Colors.red:
      stringifiedColor = 'red';
      break;
    case Colors.deepOrange:
      stringifiedColor = 'deepOrange';
      break;
    case Colors.orange:
      stringifiedColor = 'orange';
      break;
    // ...省略
  }

  return stringifiedColor;
}


// Stringで保存されたMaterialColorの名前をもとにColorの値を返す
Color stringifiedColorToColor(String stringifiedColor) {
  Color reconvertedColor;

  switch (stringifiedColor) {
    case 'pink':
      reconvertedColor = Colors.pink;
      break;
    case 'red':
      reconvertedColor = Colors.red;
      break;
    case 'deepOrange':
      reconvertedColor = Colors.deepOrange;
      break;
    case 'orange':
      reconvertedColor = Colors.orange;
      break;
    // ...省略
  }

  return reconvertedColor;
}

そうです。すみません。色の名前をStringで保存して、データを取ってくる時にそれをアプリ側でColorに戻してるだけです。おかげでコードが長ったらしくなりました。

アプリの中でユーザーに色をcolor picker(MaterialColorのみ)で選択させてそれを保存するという形をとっているので、"cyan"とか"amber"という風にデータベースにも保存されているとわかりやすいかなと思ってこれでいきました。"stringify"とはちょっと違うような気もしますが、「文字列にする」ということで多めに見てください。

もっと上手いことできたんじゃないかなとは思いますが、今回はこのように対処しました。

参考