Flutter Changenotifier class needs always to be passed in my functions

Issue

I have a FutureBuilder receiving values from a function. This is my FutureBuilder with the new context.watch syntax

final dataNotifier = Provider.of<DataNotifier>(context, listen: false);
    returnFutureBuilder(
                future: DataService().getData(dataNotifier),
                // ignore: missing_return
                builder: (context, snapshot) {
                  switch (snapshot.connectionState) {
                    case ConnectionState.none:
                      return Center(child: Text('No status', style: TextStyle(color: Colors.white),));
                      break;
                    case ConnectionState.waiting:
                      return Center(child: CircularProgressIndicator());
                      break;
                    case ConnectionState.done:
                    
    
                    return Center(
                      child:  Column(
                                    children: [
                                      Text(context.watch<Data>().myList[0].id, style: TextStyle(color: Colors.white)),
                                      Text(context.watch<Data>().myList[0].name, style: TextStyle(color: Colors.white))
                                    ],
                    ));
                   
                       //Center(child: Text('Data', style: TextStyle(color: Colors.white),));
                      break;
                    default:
                  }
                },
              ),

Everything just works fine as long I’m always passing the dataNotifier in every function. I’m not quite familiar with providers yet, how can I get that work without always passing the dataNotifier?

I assume I have to add something in my Changenotifier class? my future function getData(dataNotifier) ends with the following:

dataNotifier.myList = _myList;

And my Changenotifier class DataNotifier:

class DataNotifier with ChangeNotifier {


      List<Data> _myList = [];
      UnmodifiableListView<Data> get myList => UnmodifiableListView(_myList);
      set myList(List<Data> myList){
        _myList = myList;
        notifyListeners();
      }

Solution

The simplest working Provider example with a MVVM (Model, View, ViewModel) architecture is this below.

When data is loaded app is updated to display the new value.

You can replace the String data with anything you like, for example a list of items.

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';

void main() {
  runApp(MaterialApp(
      home: Material(
    child: ChangeNotifierProvider<DataNotifier>(
        create: (_) => DataNotifier(), child: MyApp()),
  )));
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final dataNotifier = Provider.of<DataNotifier>(context);
    if (dataNotifier.dataLoaded) return Column(
      mainAxisAlignment: MainAxisAlignment.start,
      mainAxisSize: MainAxisSize.max,
      children: [
      Text(dataNotifier.data),
      Text(
      dataNotifier.listData.fold("LIST: ", (previousValue, e) => "$previousValue [${e.id} ${e.name}]"),
    )]);
    return Text("Waiting...");
  }
}

class DataNotifier with ChangeNotifier {
  bool _dataLoaded;
  bool get dataLoaded => _dataLoaded;
  DataService _service;
  String _data;
  String get data => _data;
  List<SampleData> _listData;
  List<SampleData> get listData => _listData;

  DataNotifier() {
    _dataLoaded = false;
    _service = DataService();
    getData();
  }

  void getData() async {
    _data = await _service.getData();
    _listData = await _service.getListData();
    _dataLoaded = true;
    notifyListeners();
  }
}

class DataService {
  Future<String> getData() async {
    return Future<String>.delayed(
      const Duration(seconds: 5),
      () => 'Data Loaded',
    );
  }

  Future<List<SampleData>> getListData() async {
    return Future<List<SampleData>>.delayed(
      const Duration(seconds: 5),
      () => List.generate(100, (index) => SampleData(index, "name_$index")),
    );
  }
}

class SampleData {
  int id;
  String name;

  SampleData(this.id, this.name);
}

Answered By – camillo777

Answer Checked By – Jay B. (FlutterFixes Admin)

Leave a Reply

Your email address will not be published. Required fields are marked *