0

I'm learning flutter and trying to make a notes app and hardcode 3 notes using inherited widget and a list of map. Problem is that I get thrown this error when I try to run the app so far: I/flutter (32083): ══╡ EXCEPTION CAUGHT BY WIDGETS LIBRARY ╞═══════════════════════════════════════════════════════════ I/flutter (32083): The following NoSuchMethodError was thrown building HomeScreen(dirty, state: I/flutter (32083): _HomeScreenState#050b1): I/flutter (32083): The getter 'notes' was called on null. I/flutter (32083): Receiver: null I/flutter (32083): Tried calling: notes I/flutter (32083):

This is the code so far:

main.dart:

import 'package:flutter/material.dart';

import 'home_screen.dart';
import 'note_inherited_widget.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return NoteInheritedWidget(
          MaterialApp(
        home: HomeScreen(),
        theme: ThemeData(
            primaryColor: Colors.deepOrange, accentColor: Colors.deepPurple),
      ),
    );
  }
}

home_screen.dart

import 'package:flutter/material.dart';
import 'package:simple_notes/note_inherited_widget.dart';

class HomeScreen extends StatefulWidget {
  @override
  _HomeScreenState createState() => _HomeScreenState();
}

class _HomeScreenState extends State<HomeScreen> {
  final myController = TextEditingController();

  @override
  void dispose() {
    // Clean up the controller when the widget is disposed.
    myController.dispose();
    super.dispose();
  }

  List<Map<String, String>> get notes => NoteInheritedWidget.of(context).notes;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: Text('Simple Notes'),
          centerTitle: true,
        ),
        body: ListView.builder(itemBuilder: (context, index) {
          return Card(
            child: Column(
              children: <Widget>[
                NoteTitle(notes[index]['title']), 
                NoteText(notes[index]['text'])],
            ),
          );
        },
        itemCount: notes.length,
        ),
        bottomNavigationBar: (FlatButton(
            onPressed: () {
              showMyDialog(context);
            },
            child: Text('Add note'))));
  }

  Future<void> showMyDialog(
    BuildContext context,
  ) {
    return showDialog<void>(
        context: context,
        builder: (BuildContext context) {
          return AlertDialog(
            content: TextField(),
            actions: <Widget>[
              new FlatButton(
                  onPressed: () => Navigator.pop(context), child: Text('Save'))
            ],
          );
        });
  }
}

class NoteTitle extends StatelessWidget {
  final String title;

  NoteTitle(this.title);

  @override
  Widget build(BuildContext context) {
    return Text(
      title,
      style: TextStyle(
        fontSize: 25,
        fontWeight: FontWeight.bold
      ),
    );
  }
}

class NoteText extends StatelessWidget {
  final String text;

  NoteText(this.text);

  @override
  Widget build(BuildContext context) {
    return Text(
      text,
      style: TextStyle(
        color: Colors.grey.shade600,
      ),
      maxLines: 2,
      overflow: TextOverflow.ellipsis,
    );
  }
}

note_inherited_widget.dart

import 'package:flutter/material.dart';

class NoteInheritedWidget extends InheritedWidget {

  final notes = [
    {
      'title': 'My first title',
      'text': 'My first text'
    },
    {
      'title': 'My second title',
      'text': 'My second  text'
    },
    {
      'title': 'My third title',
      'text': 'My third text'
    }
  ];

  NoteInheritedWidget(Widget child) : super(child: child);

bool updateShouldNotify(NoteInheritedWidget oldwidget) => oldwidget.notes != notes;

  static NoteInheritedWidget of(BuildContext context) =>
    context.dependOnInheritedWidgetOfExactType(aspect: NoteInheritedWidget) as NoteInheritedWidget;
}

I also had problems trying to implement the inherited widget method, I think there might be mistakes there that I dont understand. So if any of you guys could help me with this that would be terrific. @{11488366}

Thank you in advance!

Trendy202
  • 7
  • 3

2 Answers2

0

Can you please try this;

List<Map<String, String>> notes;

@override
Widget build(BuildContext context) {
  notes = NoteInheritedWidget.of(context).notes;

instead of;

List<Map<String, String>> get notes => NoteInheritedWidget.of(context).notes;
malibayram91
  • 4,575
  • 2
  • 15
  • 19
  • Hello, thanks a lot for your answer, I tried to implement your way yet I don't think I posses enough knowledge to be able to use it effectivly. – Trendy202 Apr 19 '20 at 08:57
0

I guess you need to make a separation, make a dummy data class like this :

class DummyDataProvider{

final notes = [
    {
      'title': 'My first title',
      'text': 'My first text'
    },
    {
      'title': 'My second title',
      'text': 'My second  text'
    },
    {
      'title': 'My third title',
      'text': 'My third text'
    }
  ];
 } 

And make an instance of this class inside your widget which extends InheritedWidget so you can provide the same instance using InheritedWidget.

class NoteInheritedWidget extends InheritedWidget {

  final dummyData = DummyDataProvider();

  NoteInheritedWidget(Widget child) : super(child: child);


 @override
  bool updateShouldNotify(NoteInheritedWidget old) => dummyData != old.dummyData ;

  static DummyDataProvider of(BuildContext context) =>
    context.dependOnInheritedWidgetOfExactType<NoteInheritedWidget>().dummyData;
}

And don't forget to remove this line of code :

List<Map<String, String>> get notes => NoteInheritedWidget.of(context).notes;

And replace it with this and call of method inside didChangeDependinces method as the context is ready to use in this method :

 DummyDataProvider notes;

     @override
     void didChangeDependencies()
     {
     super.didChangeDependencies();
     notes = NoteInheritedWidget.of(context);
     }

Or you can call it in the build method.

Feel free to check dependOnInheritedWidgetOfExactType docs from here

Yusuf Abdelaziz
  • 141
  • 2
  • 5
  • First thank you for your firm answer, I tried all the code you told me and maybe I'm just too much of a beginner but right now I have two more problems depicted in the images below: https://imgur.com/a/gM1lImd https://imgur.com/a/bjAjdaw I was wondering maybe you could shed some light on how to solve this. Thank you a lot for your answer! – Trendy202 Apr 18 '20 at 19:31
  • The naming style that I used in the answer is misleading, sorry for that, you got an instance of DummyDataProvider using 'of' method, so you need to access the list of maps using notes.notes[index][key], tell me if that works. – Yusuf Abdelaziz Apr 18 '20 at 19:44
  • Thanks for the prompt answer, this was correct and now is working. Have a good day sir! – Trendy202 Apr 19 '20 at 08:56
  • I also think that you should have a look at Provider package which is quite helpful so you don't bother yourself with InheritedWidgets directly or how should the widgets update when data changes or something like that, also flutter_bloc is a great package as well. Provider : https://pub.dev/packages/provider , Flutter BLoC : https://pub.dev/packages/flutter_bloc – Yusuf Abdelaziz Apr 19 '20 at 10:58
  • Thanks for the info, I went to flutter dev and started documenting myself about the provider package, InheritedWidget is indeed a lower level solution. – Trendy202 Apr 20 '20 at 07:54