flutterdartmobile

Flutter error - NoSuchMethodErro: '[]' Dynamic call of null Receiver: Instance of 'LinkedSet<Object>'


I'm studying flutter for a personal project and i'm struggling in this error:

NoSuchMethodErro: '[]'
Dynamic call of null 
Receiver: Instance of 'LinkedSet<Object>'
Arguments [0]

Here is my simple code:

//main.dart
import 'package:flutter/material.dart';
import 'package:mictch_koko_course/pages/home_page.dart';

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

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: HomePage(),
      theme: ThemeData(
        primaryColor: Colors.yellow,
      ),
    );
  }
}

//pages/home_page.dart
import 'package:flutter/material.dart';
import 'package:mictch_koko_course/util/todo_tile.dart';

class HomePage extends StatefulWidget {
  const HomePage({super.key});

  @override
  _HomePageState createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {

  List toDoList = [
    {"Make Tutorial", false},
    {"Do Exercise", false}
  ];

  void checkBoxChanged(bool? value, int index){
    setState(() {
      toDoList[index][1] = !toDoList[index][1];
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.yellow[200],
      appBar: AppBar(
        backgroundColor: Theme.of(context).primaryColor,
        title: Center(child: Text("TO DO")),
        elevation: 0,
      ),
      body: ListView.builder(
        itemCount: toDoList.length,
        itemBuilder: (context, index){
          return TodoTile(
            taskName: toDoList[index][0],
            taskCompleted: toDoList[index][1],
            onChanged: (value) => checkBoxChanged(value, index),
          );
        }
      )
    );
  }
}

//util/todo_tile.dart
import 'package:flutter/material.dart';

class TodoTile extends StatelessWidget {
  final String taskName;
  final bool taskCompleted;
  Function(bool?)? onChanged;

  TodoTile({
    super.key,
    required this.taskName,
    required this.taskCompleted,
    required this.onChanged,
  });

  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.all(25.0),
      child: Container(
        padding: EdgeInsets.all(12),
        decoration: BoxDecoration(
          color: Colors.yellow,
          borderRadius: BorderRadius.circular(12),
        ),
        child: Row(
          children: [
            Checkbox(value: taskCompleted, onChanged: onChanged),
            Text(taskName),
          ],
        ),
      ),
    );
  }
}

I tried some fixes with this dynamic onChanged method, but I can't figure out how to fix this error. I also removed every dynamic function to test if this was the problem, but unfortunately, it wasn't.

Any help or tips to how to fix it will be welcome!


Solution

  • The issue is that you are treating Map as a list and accessing the values as an index which is not allowed accessing values from the map is done through keys like this:

    final taskName = toDoList[0]["task"]; // which will take the name of the first task in the list.
    // as you can see the first level is List so we are accessing values using index
    // `0` then we have Map and accessing its values through key `task`, `completed`
    

    correct code is:

    class _HomePageState extends State<HomePage> {
      List<Map<String, dynamic>> toDoList = [
        {"task": "Make Tutorial", "completed": false},
        {"task": "Do Exercise", "completed": false}
      ];
    
      void checkBoxChanged(bool? value, int index) {
        setState(() {
          toDoList[index]["completed"] = !toDoList[index]["completed"];
        });
      }
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          backgroundColor: Colors.yellow[200],
          appBar: AppBar(
            backgroundColor: Theme.of(context).primaryColor,
            title: Center(child: Text("TO DO")),
            elevation: 0,
          ),
          body: ListView.builder(
            itemCount: toDoList.length,
            itemBuilder: (context, index) {
              return TodoTile(
                taskName: toDoList[index]["task"], // Corrected key
                taskCompleted: toDoList[index]["completed"], // Corrected key
                onChanged: (value) => checkBoxChanged(value, index),
              );
            },
          ),
        );
      }
    }