title: Flutter Provider Nested Objects
body: <p>I'm using the <a href="https://pub.dev/packages/provider" rel="noreferrer">Provider Package</a> to manage state in my Flutter App.  I am running into issues when I start nesting my objects.  </p>
  
  <p>A very simple example: Parent A has child of type B, which has child of type C, which has child of type D.  In child D, I want to manage a color attribute.  Code example below:</p>
  
  <pre><code>import 'package:flutter/material.dart';
  
  class A with ChangeNotifier
  {
      A() {_b = B();}
  
      B _b;
      B get b =&gt; _b;
  
      set b(B value)
      {
          _b = value;
          notifyListeners();
      }
  }
  
  class B with ChangeNotifier
  {
      B() {_c = C();}
  
      C _c;
      C get c =&gt; _c;
  
      set c(C value)
      {
          _c = value;
          notifyListeners();
      }
  }
  
  class C with ChangeNotifier
  {
      C() {_d = D();}
  
      D _d;
      D get d =&gt; _d;
  
      set d(D value)
      {
          _d = value;
          notifyListeners();
      }
  }
  
  class D with ChangeNotifier
  {
      int                 _ColorIndex = 0;
      final List&lt;Color&gt;   _ColorList = [
          Colors.black,
          Colors.blue,
          Colors.green,
          Colors.purpleAccent
      ];
  
      D()
      {
          _color = Colors.red;
      }
  
      void ChangeColor()
      {
          if(_ColorIndex &lt; _ColorList.length - 1)
          {
              _ColorIndex++;
          }
          else
          {
              _ColorIndex = 0;
          }
  
          color = _ColorList[_ColorIndex];
      }
  
      Color _color;
  
      Color get color =&gt; _color;
  
      set color(Color value)
      {
          _color = value;
          notifyListeners();
      }
  }
  </code></pre>
  
  <p>Now my <strong>main.dart</strong> (which is managing my <code>Placeholder()</code> widget) contains the following:</p>
  
  <pre><code>import 'package:flutter/material.dart';
  import 'package:provider/provider.dart';
  import 'package:provider_example/NestedObjects.dart';
  
  void main() =&gt; runApp(MyApp());
  
  class MyApp extends StatelessWidget
  {
      @override
      Widget build(BuildContext context)
      {
          return MaterialApp(
              home: ChangeNotifierProvider&lt;A&gt;(
                  builder: (context) =&gt; A(),
                  child: MyHomePage()
              ),
          );
      }
  }
  
  class MyHomePage extends StatefulWidget
  {
  
      @override
      State createState()
      {
          return _MyHomePageState();
      }
  }
  
  class _MyHomePageState extends State&lt;MyHomePage&gt;
  {
      @override
      Widget build(BuildContext context)
      {
          A   a = Provider.of&lt;A&gt;(context);
          B   b = a.b;
          C   c = b.c;
          D   d = c.d;
  
          return Scaffold(
              body: Center(
                  child: Column(
                      children: &lt;Widget&gt;[
                          Text(
                              'Current selected Color',
                          ),
                          Placeholder(color: d.color,),
                      ],
                  ),
              ),
              floatingActionButton: FloatingActionButton(
                  onPressed: () =&gt; ButtonPressed(context),
                  tooltip: 'Increment',
                  child: Icon(Icons.arrow_forward),
              ),
          );
      }
  
      void ButtonPressed(BuildContext aContext)
      {
          A   a = Provider.of&lt;A&gt;(context);
          B   b = a.b;
          C   c = b.c;
          D   d = c.d;
  
          d.ChangeColor();
      }
  }
  
  </code></pre>
  
  <p>The above shows that the <strong>Placeholder Widget</strong>'s color attribute is defined by <strong>Class D</strong>'s color property <code>(A -&gt; B -&gt; C -&gt; D.color)</code>. The above code is extremely simplified, but it does show the issue I'm having.</p>
  
  <p><strong>Back to the point</strong>: how would I assign <em>child D</em>'s color property to a widget, so that when updating <em>child D</em>'s property, it also automatically updates the widget (using <code>notifyListeners()</code>, not <code>setState()</code>).</p>
  
  <p>I've used <strong>Stateless</strong>, <strong>Stateful</strong>, <strong>Provider.of</strong> and <strong>Consumer</strong>, all which gives me the same result.  Just to reiterate, the objects can't be decoupled, it has to have parent-child relationships.</p>
  
  <hr>
  
  <p><strong>EDIT</strong></p>
  
  <p>More complex example:</p>
  
  <pre><code>import 'dart:ui';
  
  enum Manufacturer
  {
      Airbus, Boeing, Embraer;
  }
  
  class Fleet
  {
      List&lt;Aircraft&gt; Aircrafts;
  }
  
  class Aircraft
  {
      Manufacturer        AircraftManufacturer;
      double              EmptyWeight;
      double              Length;
      List&lt;Seat&gt;          Seats;
      Map&lt;int,CrewMember&gt; CrewMembers;
  }
  
  class CrewMember
  {
      String Name;
      String Surname;
  }
  
  class Seat
  {
      int     Row;
      Color   SeatColor;
  }
  </code></pre>
  
  <p>The above code is a simplified version of a real world example.  As you can imagine the rabbit hole can go deeper and deeper.  So, what I meant by the <code>A</code> through <code>D</code> example was trying to simplify the convolution of the situation.</p>
  
  <p>Lets say for example you want to display and/or change a crew members' name in a widget.  In the app itself you would typically select an <code>Aircraft</code> from the <code>Fleet</code> (passed to widget by <code>List</code> index), then select a <code>CrewMember</code> from the <code>Aircraft</code> (passed by <code>Map</code> key) and then display/change the <code>Name</code> of <code>CrewMember</code>.</p>
  
  <p>In the end your widget will be able to see what Crew Member's name you are referring to by using the passed in <code>Aircrafts</code> index and <code>CrewMembers</code> key.</p>
  
  <p>I'm definitely open to a better architecture and designs.</p>