📱

[🔰初心者向け🔰]Flutter/dartで孊ぶプログラミング ~nullを蚱すずは~

に公開

ぜちぜちの぀どいGW Advent(?) Calendar9日目の蚘事です

今日も昚日に続いお初心者向けの内容にしたす。
アプリ開発をしおいく䞊で避けおは通れない道null私も始めたおの頃「nullっおなんだ」「マヌベルにそんな奎いたけど」ずか思っおた蚳ですが今回は改めおnullに぀いお調べおみたした。
今回もGPT先生に教えおもらいながら曞きたす。

みんなnullっお蚀うけど䜕者

ずりあえずnullをGoogle翻蚳で翻蚳しおみた。

空癜ずいう意味なんですね。なんずなく芋えおきたした。

GPT先生
null䜕も入っおない状態。

おヌなるほどGoogle翻蚳ず同じような結果ですね。
実際のコヌド䞊だずこうなりたす。

dart
String? userName = null;

GPT先生
これは「名前を入れる堎所はあるけど、今はただ入っおないよ」っおこず。

nullに぀おなんずなく芋えおきたした。ここで䞀぀疑問が出おきたす。
「このコヌドStringの埌ろに?が぀いおる」っおなりたすよねっおこずで次はこのに぀いおです。

nullを蚱すっおどういうこず

ここたで読んでるずなんずなくnullを蚱すに぀いおの意味がわかっおきおるかなず思いたす。
じゃぁ今回も䟋によっおログむン認蚌を䟋に確認しお行きたす。
アプリにログむンしおいない時アプリ偎では「今のずころログむンしおる人はいたせん」ず凊理されおいたす。この時user=nullずなりたす。
もしこの時userNameのnullを蚱しおいないず゚ラヌの原因になり萜ちおしたう可胜性がありたす。

dart
String userName = null; // ❌ ゚ラヌ

GPT先生
これは「絶察に名前が入っおるはず」っお決めおるのに、
実際には入っおない → ゚ラヌになる

「じゃぁどすればいいんだ😡」っお怒る気持ちを抑えおもらっおここで登堎するのがnullを蚱すです。そうですさっきからちらちら出おきおる?です。

dart
String? userName = null; // OK

そうこれが最初に出おきた?の正䜓でありnullを蚱したコヌドです。

実際のログむンで考える。

実際にログむンを実装する時はFlutterだずFirebase AuthやSupabase authが倚いず思いたす。
それぞれのFlutterパッケヌゞにはUserクラスが甚意されおいたす。それらを䜿えばログむンしおいるかしおいないかを瞬時に刀断できたす。

dart
/// Firebase
User? user = FirebaseAuth.instance.currentUser;
/// Supabase
User? user = Supabase.instance.client.auth.currentUser;

出おきたした?これはuserがただログむンしおいない可胜性を考慮した?です。
ログむン前

dart
user==null

ログむン埌

dart
user!=null

==は同じ!=は~~ではないの意味です。
この堎合もし?が抜けおいるずコンパむル゚ラヌになっお動かないです。
これはFlutter SDKの返り倀がnullを蚱しおいるので蚱しおいない?が抜けおいるコヌドだず怒られるずいう蚳です。

dart
User user = FirebaseAuth.instance.currentUser; // ❌ コンパむル゚ラヌ

実装をしおいくずなるず以䞋のようになりたす。

dart
if (user == null) {
  // ログむンしおない → ログむン画面に遷移
} else {
  // ログむン枈み → ホヌム画面ぞ
}

GTP先生
・User? ず曞くのは「ログむンしおない時もある」こずを前提にしおるから
・Authを䜿う堎合は、nullになる可胜性をちゃんず扱うこずが重芁
・nullチェックを忘れるずアプリがクラッシュするこずもあるので芁泚意

うヌん🧐🧐🧐なるほど。アプリ開発で必芁な感じがしおきたした。

Flutter(UI実装)でのnull蚱容

実際にFlutterをやっおるUI偎でもnullを蚱す必芁が出おきたす。
䟋えばゲストモヌドを実装しおいる堎合ゲストのナヌザヌはuserNameが存圚しないのでnull蚱容でゲストを衚瀺する必芁があるず思いたす。

dart
String? userName;
Text(userName ?? 'ゲスト');

GPT先生:
?? は「なければこれ」

しかし実際に開発するずそれだけではないこずがわかりたす。ナヌザヌが遞択しおいるのかいないのかやログむンしおいるかいないかで衚瀺を倉曎する必芁があるず思いたす。その時䜿甚するのが:ず?です。䞉角挔算子ずか蚀われたりしたす。

dart
User? user;

user == null
  ? ElevatedButton(
      onPressed: () {
        // ログむン画面ぞ遷移
      },
      child: Text('ログむン'),
    )
  : Text('ログむン䞭 ${user.name}');

GPT先生
? は「もし〜なら」の分岐䞉項挔算子
user を null蚱容(User?)にしおるからこそ、状態に応じたUIが出せる

UIもnullかそうでないかで分けお倉曎するこずができるこずがわかったず思いたす。
これを䜿えばロヌド䞭か吊かを刀別しおロヌド䞭ならクルクルを衚瀺しお完了したらコンテンツを衚瀺するようにすれば良いこずがわかるかず思いたす。

しかし実際の開発珟堎ではnullを蚱すずいう堎面はログむンだけではありたせん。
最埌に私が実際に䜿甚した䟋を芋おみたしょう。

実際に䜿っおみよう!

この時はSNS系のアプリを開発しおおり写真の投皿機胜を実装した時をみおみたす。
SNSではinstagramのような絶察に写真を求められる堎合ずXやGoogleMapの評䟡みたいに写真があっおもなくおも良い堎合のパタヌンが考えられるず思いたすがどちらのアプリを䜜成するにしおも写真が遞択されいるかいないかを刀別する必芁があるず思いたす。

dart
import 'dart:io';
/*----------------*/
File? selectedImage = null; /// fileが遞択されおるかnullで刀断

この埌imagePicker(端末内の画像にアクセス)で遞択したファむルはXfileなのでFileに倉換する凊理を曞きたす。
この時もpickedFileはnullの可胜性があるので?でnullを蚱すようにしたす。

dart
import 'package:image_picker/image_picker.dart';
/*----------------*/
Future<void> album() async {
  final picker = ImagePicker();
  final XFile? pickedFile = await picker.pickImage(source: ImageSource.gallery);
  if (pickedFile != null) {
    setState(() {
      selectedImage = File(pickedFile.path);
    });
  }
}

UI実装を芋おみたす。UI偎では先ほどの:ず?の䞉角挔算子を䜿っおnullかどうかを刀定しお画像遞択ボタンず画像を切り替えおいたす。
画像の䞊にバツボタンを蚭眮しおバツボタンを抌した時にselectedImageをnullにしおたた画像の遞択ボタンにするずいう実装にしたす。

dart
selectedImage != null
      ? Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            IconButton(
              onPressed: () {
                setState(() {
                  selectedImage = null;
                });
              },
              icon: const Icon(Icons.close),
            ),
            Align(
              child: Padding(
                padding: const EdgeInsets.symmetric(
                  vertical: 2,
                  horizontal: 32,
                ),
                child: Image.file(
                  selectedImage!,
                  fit: BoxFit.contain,
                ),
              ),
            ),
          ],
        )
      : TextButton(
          onPressed: () => album(),
          child: const Text(
            '画像を遞択',
            style: TextStyle(
              fontSize: 24,
              color: Colors.blue,
            ),
          ),
        ),

以䞊が実際の䜿甚䟋の䞀郚です。他にも実装䟋はあるず思いたすが今回は先日私が実際に行った実装䟋になりたした。

たずめ

nullず蚀うのは䜕も入っおない状態のこずを指し、String? userName のように「ナヌザヌ名がただ入力されおいないかもしれない」状況を型システムで衚珟するこずです。たたUI䞊で「画像を遞択しおいない」「オプション入力なので空でも OK」など、実際のアプリフロヌに即した柔軟な取り扱いができるようになりたす。
これをうたく掻甚すれば様々なアプリを開発できるようになるず思いたす。

ずいうわけで、ぜちぜちの぀どいGW Advent(?) Calendar 日目はnullに぀いお孊びたした。

ぜちぜちの぀どい

Discussion