Home > database >  The non-nullable local variable 'title' must be assigned before it can be used. Flutter er
The non-nullable local variable 'title' must be assigned before it can be used. Flutter er

Time:10-01

I want to take user input from the textfield widget and assign in title variable as in this code

import 'package:flutter/material.dart';

class AddTaskScreen extends StatelessWidget {
  final Function callBack; // function

  AddTaskScreen({required this.callBack});

  @override
  Widget build(BuildContext context) {
    String title; // declaring the variable
    return Container(
      height: 350,
      color: Color(0xff757575),
      child: Container(
        padding: EdgeInsets.all(20),
        decoration: BoxDecoration(
          color: Colors.white,
          borderRadius: BorderRadius.only(
            topRight: Radius.circular(20),
            topLeft: Radius.circular(20),
          ),
        ),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.stretch,
          children: [
            Text(
              'Add Task',
              textAlign: TextAlign.center,
              style: TextStyle(
                color: Colors.lightBlueAccent,
                fontSize: 24,
              ),
            ),
            SizedBox(
              height: 20,
            ),
            TextField(
              textAlign: TextAlign.center,
              autofocus: false,
              style: TextStyle(
                color: Colors.black,
                fontSize: 15,
              ),
              onChanged: (value) {
                title = value; // taking the user input
              },
              decoration: InputDecoration(
                focusColor: Colors.lightBlueAccent,
                hintText: 'Type a Task',
                hintStyle: TextStyle(
                  color: Colors.grey,
                  fontSize: 12,
                ),
              ),
            ),
            SizedBox(
              height: 20,
            ),
            TextButton(
              onPressed: () {
                callBack(title); // error
              },
              style: TextButton.styleFrom(
                backgroundColor: Colors.lightBlueAccent,
              ),
              child: Text(
                'Add',
                style: TextStyle(
                  color: Colors.white,
                  fontSize: 18,
                ),
              ),
            ),
          ],
        ),
      ),
    );
  }
}

as you can see there is a function callBack variable. it has the String parameter when I pass title in this function it gives me a warning. here is the code for the callBack when will send this information.

import 'package:flutter/material.dart';
import 'package:todoey/models/Task.dart';
import 'package:todoey/screens/add_task_screen.dart';
import 'package:todoey/screens/bottom_section.dart';
import 'package:todoey/screens/top_section.dart';

class TasksScreen extends StatefulWidget {
  @override
  State<TasksScreen> createState() => _TasksScreenState();
}

class _TasksScreenState extends State<TasksScreen> {
  List<Task> tasks = [];

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          showModalBottomSheet(
            context: context,
            builder: (context) => SingleChildScrollView(
              child: Container(
                padding: EdgeInsets.only(
                    bottom: MediaQuery.of(context).viewInsets.bottom),
                child: AddTaskScreen(
                  callBack: (String taskTitle) {
                    setState(() {
                      print(taskTitle);
                      tasks.add(
                        Task(
                          name: taskTitle,
                        ),
                      );
                    });
                    Navigator.pop(context);
                  },
                ).build(context),
              ),
            ),
          );
        },
        child: Icon(
          Icons.add,
          color: Colors.white,
          size: 35,
        ),
        elevation: 5,
        backgroundColor: Colors.lightBlueAccent,
      ),
      backgroundColor: Colors.lightBlueAccent,
      body: SafeArea(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.start,
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            TopSection(),
            SizedBox(
              height: 30,
            ),
            BottomSection(tasks: tasks),
          ],
        ),
      ),
    );
  }
}

for the main class, here is the code.

import 'package:flutter/material.dart';
import 'package:todoey/screens/task_screen.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: TasksScreen(),
    );
  }
}

CodePudding user response:

In flutter, you want to store mutable objects (such as your title) in a State. This is because the build function can theoretically be called many times, you have no control over it. Therefore, storing the variable in the State of an object allows you to keep it "alive" while build is called many times.

Here is your example, adapted to work as intended:

import 'package:flutter/material.dart';

class AddTaskScreen extends StatefulWidget {
  final Function callBack; // function

  AddTaskScreen({required this.callBack});

  @override
  State<AddTaskScreen> createState() => _AddTaskScreenState();
}

class _AddTaskScreenState extends State<AddTaskScreen> {
  /// Declare title in the state, so that its a long lived object
  var title = ""; // Initialize it (likely as empty)
  
  @override
  Widget build(BuildContext context) {

    return Container(
      height: 350,
      color: Color(0xff757575),
      child: Container(
        padding: EdgeInsets.all(20),
        decoration: BoxDecoration(
          color: Colors.white,
          borderRadius: BorderRadius.only(
            topRight: Radius.circular(20),
            topLeft: Radius.circular(20),
          ),
        ),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.stretch,
          children: [
            Text(
              'Add Task',
              textAlign: TextAlign.center,
              style: TextStyle(
                color: Colors.lightBlueAccent,
                fontSize: 24,
              ),
            ),
            SizedBox(
              height: 20,
            ),
            TextField(
              textAlign: TextAlign.center,
              autofocus: false,
              style: TextStyle(
                color: Colors.black,
                fontSize: 15,
              ),
              onChanged: (value) {
                title = value; // taking the user input
              },
              decoration: InputDecoration(
                focusColor: Colors.lightBlueAccent,
                hintText: 'Type a Task',
                hintStyle: TextStyle(
                  color: Colors.grey,
                  fontSize: 12,
                ),
              ),
            ),
            SizedBox(
              height: 20,
            ),
            TextButton(
              onPressed: () {
                widget.callBack(title); // error
              },
              style: TextButton.styleFrom(
                backgroundColor: Colors.lightBlueAccent,
              ),
              child: Text(
                'Add',
                style: TextStyle(
                  color: Colors.white,
                  fontSize: 18,
                ),
              ),
            ),
          ],
        ),
      ),
    );
  }
}

CodePudding user response:

So you are using a stateless widget and so you onChanged function will not work because the state of a stateless widget will not change to render the new value of the title, so you could change it to a stateful widget to see the effect.

  • Related