Why my list is not rebuild after rearanging items

1,229

Following is the working code. You were consuming the default values and were not consuming the change. Please refer the code below.

Edited

You should use ChangeNotifierProvider.value for this use-case instead of ChangeNotifierProvider. Difference

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

class InnerProvider extends ChangeNotifier {
  int pid;
  InnerProvider(this.pid);

  get id => pid;

  set id(int i) {
    pid = i;
    notifyListeners();
  }
}

class OuterProvider extends ChangeNotifier {
  List _data = [
    InnerProvider(1),
    InnerProvider(3),
    InnerProvider(4),
    InnerProvider(5),
  ];

  get data => _data;

  addToData(var item) {
    data.add(item);
    notifyListeners();
  }

  reShuffle() {
    data.shuffle();
    notifyListeners();
  }

  changeId(var i) {

    var dtIndex = _data.indexOf(i);
    _data[dtIndex].id = Random().nextInt(99);
  }
}

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return ChangeNotifierProvider<OuterProvider>(
        create: (_) => OuterProvider(),
        child: MaterialApp(
          title: 'Flutter Demo',
          theme: ThemeData(
            primarySwatch: Colors.blue,
          ),
          home: MyHomePage(title: 'Why this does not work?'),
        ));
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

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

class _MyHomePageState extends State<MyHomePage> {
  List outerData;

  void reShuffleData() {
    Provider.of<OuterProvider>(context).reShuffle();
  }

  @override
  Widget build(BuildContext context) {
    outerData = Provider.of<OuterProvider>(context, listen: true).data;
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
          child: ListView.builder(
              itemCount: outerData.length,
              itemBuilder: (context, int i) {
                return  ChangeNotifierProvider<InnerProvider>.value(
                  value: outerData[i],
                  child: InnerChild(),
                );
              })),
      floatingActionButton: FloatingActionButton(
        onPressed: reShuffleData,
        tooltip: 'Shuffle',
        child: Icon(Icons.add),
      ),
    );
  }
}

class InnerChild extends StatelessWidget {
  Widget build(BuildContext context) {
    var prov = Provider.of<InnerProvider>(context);
    return Row(mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[
      GestureDetector(
          onTap: () {
            Provider.of<OuterProvider>(context).changeId(prov);
          },
          child: Text(
            Provider.of<InnerProvider>(context).id.toString(),
            style: TextStyle(fontSize: 40),
          )),
    ]);
  }
}
Share:
1,229
Kozubi
Author by

Kozubi

Updated on December 16, 2022

Comments

  • Kozubi
    Kozubi over 1 year

    This is toy app using Flutter and Provider package. My goals are simple: - OuterProvider have data which is used to build a list (ListView.builder) - Outer provider have Shuffle button which shuffle inner list - Inner Widgets (Rows) uses InnerProvider to proceed with changing data randomly

    When i click on InnerWidget - provider updates data correctly But when I shuffle data, even if data is shuffled. Build method is run but my widgets list is not affected….

    Here is sample code

    import 'package:flutter/material.dart';
    import 'package:provider/provider.dart';
    import 'package:flutter/foundation.dart';
    import 'dart:math';
    
    class InnerProvider extends ChangeNotifier {
      int pid;
      InnerProvider(this.pid);
    
      get id => pid;
    
      set id(int i) {
        pid = i;
        notifyListeners();
      }
    }
    
    class OuterProvider extends ChangeNotifier {
      List _data = [
        InnerProvider(1),
        InnerProvider(3),
        InnerProvider(4),
        InnerProvider(5),
      ];
    
      get data => _data;
    
      addToData(var item) {
        data.add(item);
        notifyListeners();
      }
    
      reShuffle() {
        data.shuffle();
        notifyListeners();
      }
    
      changeId(var i) {
    
        var dtIndex = _data.indexOf(i);
        _data[dtIndex].id = Random().nextInt(99);
      }
    }
    
    void main() => runApp(MyApp());
    
    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return ChangeNotifierProvider<OuterProvider>(
            create: (_) => OuterProvider(),
            child: MaterialApp(
              title: 'Flutter Demo',
              theme: ThemeData(
                primarySwatch: Colors.blue,
              ),
              home: MyHomePage(title: 'Why this does not work?'),
            ));
      }
    }
    
    class MyHomePage extends StatefulWidget {
      MyHomePage({Key key, this.title}) : super(key: key);
    
      final String title;
    
      @override
      _MyHomePageState createState() => _MyHomePageState();
    }
    
    class _MyHomePageState extends State<MyHomePage> {
      List outerData;
    
      void reShuffleData() {
        Provider.of<OuterProvider>(context).reShuffle();
      }
    
      @override
      Widget build(BuildContext context) {
        outerData = Provider.of<OuterProvider>(context, listen: true).data;
        return Scaffold(
          appBar: AppBar(
            title: Text(widget.title),
          ),
          body: Center(
              child: ListView.builder(
                  itemCount: outerData.length,
                  itemBuilder: (context, int i) {
                    return ChangeNotifierProvider<InnerProvider>(
                        create: (_) => outerData[i], child: InnerChild());
                  })),
          floatingActionButton: FloatingActionButton(
            onPressed: reShuffleData,
            tooltip: 'Shuffle',
            child: Icon(Icons.add),
          ),
        );
      }
    }
    
    class InnerChild extends StatelessWidget {
      Widget build(BuildContext context) {
        var prov = Provider.of<InnerProvider>(context);
        return Row(mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[
          GestureDetector(
              onTap: () {
                Provider.of<OuterProvider>(context).changeId(prov);
              },
              child: Text(
                Provider.of<InnerProvider>(context).id.toString(),
                style: TextStyle(fontSize: 40),
              )),
        ]);
      }
    }