Flutter アプリ

【Flutter】グローバル変数とNull Safetyについて

以下のコードのの_date(★の部分)で、"Undefined name '_date'.\nTry correcting the name to one that is defined, or defining the name."のエラーメッセージが表示されます。本記事ではその原因と対処方法をお伝えします。

import 'package:flutter/material.dart';
// --中略--
class AddNote extends StatefulWidget {
  const AddNote({Key? key}) : super(key: key);

  @override
  State<AddNote> createState() => _AddNoteState();
}

class _AddNoteState extends State<AddNote> {
  String? _selectedCategory; // ?はnullになってもいい記号
  String? _selectedItem;
  int? _currentValue;
// --中略--
      body: Column(
        children: <Widget>[
          SizedBox(height: 10),
          Row(
            mainAxisAlignment: MainAxisAlignment.spaceAround, // これで両端に寄せる
            children: <Widget>[
              Icon(Icons.schedule),
              Container(
                padding: const EdgeInsets.symmetric(vertical: 5, horizontal: 15),               
                child: Text(DateFormat('yyyy/MM/dd').format(_date).toString(), ★
// --中略--
  void _selectDate(BuildContext context) async {
    DateTime? _newSelectedDate = await showDatePicker(
      // locale: const Locale("ja"),
      context: context,
      initialDate:  _date, 
      firstDate: DateTime(2000),
      lastDate: DateTime(2040),
    );

    if (_newSelectedDate != null) {
      // 日時反映
      DateTime? _date;
      setState(() => _date = _newSelectedDate); 
    }
  }

}

本記事では、 そのエラーの原因と対処方法を紹介します。

本記事の想定読者

  • Flutterでアプリを開発している人

開発環境

$ flutter doctor
Doctor summary (to see all details, run flutter doctor -v):
[√] Flutter (Channel stable, 3.0.5, on Microsoft Windows [Version 10.0.19045.3208], locale ja-JP)
[√] Android toolchain - develop for Android devices (Android SDK version 32.0.0)
[√] Chrome - develop for the web
[√] Visual Studio - develop for Windows (Visual Studio Community 2022 17.1.4)
[√] Android Studio (version 2021.1)
[!] Android Studio (version 4.1)
    X Unable to determine bundled Java version.
[!] Android Studio (version 4.2)
    X Unable to determine bundled Java version.
[√] VS Code (version 1.81.0)
[√] Connected device (4 available)
[√] HTTP Host Availability

! Doctor found issues in 2 categories.

pubspec.yaml

dependencies:
  flutter:
    sdk: flutter


  # The following adds the Cupertino Icons font to your application.
  # Use with the CupertinoIcons class for iOS style icons.
  cupertino_icons: ^1.0.2
  sticky_grouped_list: ^3.1.0
  intl: ^0.18.1
  google_fonts: ^4.0.4
  sqflite: ^2.0.3+1
  numberpicker: ^2.1.2

原因

selectDateメソッドにある、_dateをDateTime型で宣言していますが、その変数はローカル変数になります。そのため、★の_dateはselectDateメソッドの_dateを参照できず、本エラーメッセージが表示されることになります。

対処方法

対処方法はclassの直後に、"DateTime _date"を追加する事です。

下記のコードでは、"DateTime _date = DateTime(DateTime.now().year, DateTime.now().month, DateTime.now().day);"を今日の日付を値として、変数を宣言していますが、今日の日付の値でない場合は、"DateTime? _date"として、Nullを許容する形で変数を宣言します。

また、追加した_dateはグローバル変数なので、_selectDateメソッドの_dateは不要になります。

import 'package:flutter/material.dart';
// --中略--
class AddNote extends StatefulWidget {
  const AddNote({Key? key}) : super(key: key);

  @override
  State<AddNote> createState() => _AddNoteState();
}

class _AddNoteState extends State<AddNote> {
  String? _selectedCategory; // ?はnullになってもいい記号
  String? _selectedItem;
  int? _currentValue;
 DateTime _date = DateTime(DateTime.now().year, DateTime.now().month, DateTime.now().day); // 追加
// --中略--
      body: Column(
        children: <Widget>[
          SizedBox(height: 10),
          Row(
            mainAxisAlignment: MainAxisAlignment.spaceAround, // これで両端に寄せる
            children: <Widget>[
              Icon(Icons.schedule),
              Container(
                padding: const EdgeInsets.symmetric(vertical: 5, horizontal: 15),               
                child: Text(DateFormat('yyyy/MM/dd').format(_date).toString(), 
// --中略--
  void _selectDate(BuildContext context) async {
    DateTime? _newSelectedDate = await showDatePicker(
      // locale: const Locale("ja"),
      context: context,
      initialDate:  _date, 
      firstDate: DateTime(2000),
      lastDate: DateTime(2040),
    );

    if (_newSelectedDate != null) {
      // 日時反映
      DateTime? _date; // 削除
      setState(() => _date = _newSelectedDate); 
    }
  }

}

-Flutter, アプリ