Flutter The method '[]' was called on null

-1

I am running my app and getting the error:

"NoSuchMethodError: The Method '[ ]' was called on null. Receiver: null. Tried calling: ."

import 'dart:async';
import 'dart:convert';
import 'package:flutter/material.dart';

import '../model/Lesson.dart';


class MobileModeScreen extends StatefulWidget {

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


class _MobileModeScreenState extends State<MobileModeScreen> {

  List<Lesson> _lesson;


  @override
  void initState() {
    super.initState();
    Future.delayed(Duration.zero,() {
      getLessonFromJSON(context);
    });
    print("lessonDescription: ${_lesson[0].lessonTitle}");
  }

  Future<List<Lesson>> getLessonFromJSON(BuildContext context) async {
    String jsonString = await DefaultAssetBundle.of(context).loadString("assets/lessons/lessons.json");

    return await Future.delayed(Duration.zero,() {
      List<dynamic> data = jsonDecode(jsonString);
      List<Lesson> lesson = data.map( (f) => Lesson.fromJSON(f) ).toList();
      _lesson = lesson;
      print("lessonDescription: ${_lesson[0].lessonTitle}");
      return _lesson;
    });
  }


  @override
  Widget build(BuildContext context) {

    return Directionality(
      textDirection: TextDirection.rtl,
      child: Scaffold(
        appBar: AppBar(
          title: Container(
            padding: const EdgeInsets.fromLTRB(10, 0, 10, 0),
            decoration: BoxDecoration(
              color: Color(0xffFFFFFF),
              border: Border.all(
                color: Color(0xffF5ED02),
                width: 3,
              ),
              borderRadius: BorderRadius.circular(25.0),
            ),
            child: Text("lessonDescription: ${_lesson[0].lessonTitle}",
              style: TextStyle(
                //fontFamily: "Uthmani",
                color: Color(0xff225587),
              ),
            ),
          ),
          centerTitle: true,
          backgroundColor: Color(0xff7F3F96),
        ),

        body: ListView(
          padding: const EdgeInsets.fromLTRB(5, 15, 5, 5),
          children: <Widget>[
          ],
        ),
        backgroundColor: Color(0xffF0E4F2),
      ),
    );
  }
}

I'm not getting the error when I try to access the value from the getLessonFromJSON function, but outside of the function, it's not working at all.

The error I get:

════════ Exception caught by widgets library ═══════════════════════════════════════════════════════
The following NoSuchMethodError was thrown building Builder:
The method '[]' was called on null.
Receiver: null
Tried calling: [](0)

The relevant error-causing widget was: 
  MaterialApp file:///home/hmalabeh/AndroidStudioProjects/Flutter/Bounyan/boynyan_final/lib/main.dart:12:12
When the exception was thrown, this was the stack: 
#0      Object.noSuchMethod (dart:core-patch/object_patch.dart:53:5)
#1      _MobileModeScreenState.initState (package:boynyanfinal/screens/mobile_mode_screen.dart:26:40)
#2      StatefulElement._firstBuild (package:flutter/src/widgets/framework.dart:4355:58)
#3      ComponentElement.mount (package:flutter/src/widgets/framework.dart:4201:5)
#4      Element.inflateWidget (package:flutter/src/widgets/framework.dart:3194:14)
...

Can someone help please.

Update: I want to be able to use what I get from the function getLessonFromJSON in the build method like I'm using in the Text filed in the AppBar

flutter
dart
asked on Stack Overflow Jun 14, 2020 by Hassan Malaabeh • edited Jun 14, 2020 by Hassan Malaabeh

4 Answers

0

Move the get data to a different function and await the response:

@override
void initState() {
  super.initState();
  load();
}

void load() async {
  setState(() {
    await getLessonFromJSON(context);
  });
}

Also place a loader anywhere you're using _lesson, example in your Appbar:

var text = _lesson == null ? 'Loading...' : 'lessonDescription: ${_lesson[0].lessonTitle}';
Text(text,
  style: TextStyle(
  //fontFamily: "Uthmani",
    color: Color(0xff225587),
  ),
)

answered on Stack Overflow Jun 14, 2020 by Sami Haddad • edited Jun 14, 2020 by Sami Haddad
0

_lesson is null because its value is assigned only when Future.delayed is resolved.

To solve it, either move print("lessonDescription: ${_lesson[0].lessonTitle}"); inside Future handler (after getLessonFromJSON(context);) or just remove that line at all because as far as I can suppose, it's needed only for debugging purposes.

This should work:

  void initState() {
    super.initState();
    Future.delayed(Duration.zero,() {
      getLessonFromJSON(context);
      print("lessonDescription: ${_lesson[0].lessonTitle}");
    });
  }
answered on Stack Overflow Jun 14, 2020 by Andrey Ozornin
0

You should initialize '_lesson' with an empty list ``` List _lesson = [];```` And then add item to this list in initState by using _lesson.add(item) and called setState to update the state of app. This will work but you should FutureBuilder for async operations and use provider or bloc for better State management

answered on Stack Overflow Jun 14, 2020 by Sachin Bhankhar
0

I've added the setState() inside the getLessonFromJSON and I've added a loader in the places I use values from _lesson as @Sami suggested.

_lesson doesn't need to ve initialized.

@override
  void initState() {
    super.initState();
    getLessonFromJSON(context);
  }

  Future<List<Lesson>> getLessonFromJSON(BuildContext context) async {
    String jsonString = await DefaultAssetBundle.of(context).loadString("assets/lessons/lessons.json");

    try{
      return await Future.delayed(Duration.zero,() {
        List<dynamic> data = jsonDecode(jsonString);
        List<Lesson> lesson = data.map( (f) => Lesson.fromJSON(f) ).toList();
        setState(() {
          _lesson = List.from(lesson);
        });
        print("[getLessonFromJSON] lessonDescription: ${lesson[0].lessonTitle}");
        return lesson;
      });
    } catch(e){
      print(e);
    }
  }

The loader

_lessonTitle = _lesson == null ? 'Loading...' : _lesson[0].lessonTitle;
answered on Stack Overflow Jun 14, 2020 by Hassan Malaabeh

User contributions licensed under CC BY-SA 3.0