Using Selector in Provider
Tags: flutter, dart, webdev, productivity
Published: 2020-09-19 14:29:34

*In case it helped :)*
<a href="https://www.buymeacoffee.com/aseemwangoo" target="_blank"><img src="https://www.buymeacoffee.com/assets/img/custom_images/orange_img.png" alt="Pass Me A Coffee!!" style="height: 41px !important;width: 174px !important;box-shadow: 0px 3px 2px 0px rgba(190, 190, 190, 0.5) !important;-webkit-box-shadow: 0px 3px 2px 0px rgba(190, 190, 190, 0.5) !important;" ></a>

<!-- wp:heading {"level":3} -->
<h3>Begin…</h3>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>View the demo here</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p><strong><em>Website: </em></strong><a rel="noreferrer noopener" href="https://web.flatteredwithflutter.com/#/" target="_blank"><strong><em>https://web.flatteredwithflutter.com/#/</em></strong></a></p>
<!-- /wp:paragraph -->

{% youtube bYQJp8XQd6U %}

<!-- wp:paragraph -->
<p>We will cover briefly about</p>
<!-- /wp:paragraph -->

<!-- wp:list {"ordered":true} -->
<ol><li>Selector&nbsp;</li><li>Using Selector with Provider</li></ol>
<!-- /wp:list -->

####Article here: https://flatteredwithflutter.com/using-selector-in-provider/

<!-- wp:heading {"level":4} -->
<h4><strong>Current Status</strong></h4>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>Let's start by describing what we have currently. In our demo, we have an input form with 3 fields:</p>
<!-- /wp:paragraph -->

<!-- wp:list -->
<ul><li>Name Field</li><li>Age Field</li><li>Email Field</li></ul>
<!-- /wp:list -->

<!-- wp:image -->
<figure class="wp-block-image"><img src="https://cdn-images-1.medium.com/max/1600/1*xgjWAQHUbp9mVwCUXiE5_w.png" alt="Using Selector in Provider"/><figcaption>Using Selector in Provider</figcaption></figure>
<!-- /wp:image -->

<!-- wp:separator -->
<hr class="wp-block-separator"/>
<!-- /wp:separator -->

<!-- wp:paragraph -->
<p>There are 3 text fields, which basically show us the values inside each of the input fields.</p>
<!-- /wp:paragraph -->

<!-- wp:separator -->
<hr class="wp-block-separator"/>
<!-- /wp:separator -->

<!-- wp:heading {"level":4} -->
<h4>Approach 1 (All this time I&nbsp;took)</h4>
<!-- /wp:heading -->

<!-- wp:image {"align":"center"} -->
<div class="wp-block-image"><figure class="aligncenter"><img src="https://cdn-images-1.medium.com/max/1200/1*o9p-7-2z1wt2GpbRaE0gIQ.png" alt="Using Selector in Provider"/><figcaption>Using Selector in&nbsp;Provider</figcaption></figure></div>
<!-- /wp:image -->

<!-- wp:paragraph -->
<p>As per this approach, we would have a&nbsp;</p>
<!-- /wp:paragraph -->

<!-- wp:list -->
<ul><li><strong>ChangeNotifierProvider</strong>, at the top of the widget tree.</li><li>Followed by a <strong>consumer</strong>, before we start our form</li><li>Finally, our Form UI</li></ul>
<!-- /wp:list -->

<!-- wp:paragraph -->
<p><strong>Things to consider:</strong></p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>Your Form fields will undergo unnecessary builds. Let me explain.</p>
<!-- /wp:paragraph -->

<!-- wp:quote -->
<blockquote class="wp-block-quote"><p>For instance, say you are entering the age field, other fields (name and email field), will continue rebuilding since the Consumer widget is above the Form.</p></blockquote>
<!-- /wp:quote -->

<!-- wp:paragraph -->
<p>This is true for any other field also.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>As per the Consumer documentation:</p>
<!-- /wp:paragraph -->

<!-- wp:quote -->
<blockquote class="wp-block-quote"><p><a href="https://pub.dev/documentation/provider/latest/provider/Consumer/builder.html" rel="noreferrer noopener" target="_blank">builder</a> may be called multiple times (<strong>such as when the provided value change</strong>).</p></blockquote>
<!-- /wp:quote -->

<!-- wp:paragraph -->
<p>In our case, we just have 3 fields inside FormUI, so we can go with approach1, but what if we had a complex UI, think about it!</p>
<!-- /wp:paragraph -->

<!-- wp:heading {"level":4} -->
<h4>Approach 2 (Using Selector in Provider)</h4>
<!-- /wp:heading -->

<!-- wp:image -->
<figure class="wp-block-image"><img src="https://cdn-images-1.medium.com/max/1600/1*lk-_LRduiJAuLD9KqzJq-w.png" alt="Using Selector in Provider"/><figcaption>Using Selector in&nbsp;Provider</figcaption></figure>
<!-- /wp:image -->

<!-- wp:paragraph -->
<p>When I started to use Provider in Flutter, most of the times, it was either</p>
<!-- /wp:paragraph -->

<!-- wp:list -->
<ul><li><a href="https://pub.dev/documentation/provider/latest/provider/ChangeNotifierProvider-class.html" rel="noreferrer noopener" target="_blank">ChangeNotifierProvider</a></li><li><a href="https://pub.dev/documentation/provider/latest/provider/Consumer-class.html" rel="noreferrer noopener" target="_blank">Consumer</a>, <a href="https://pub.dev/documentation/provider/latest/provider/Consumer2-class.html" rel="noreferrer noopener" target="_blank">Consumer2</a>, etc</li><li><a href="https://pub.dev/documentation/provider/latest/provider/ValueListenableProvider-class.html" rel="noreferrer noopener" target="_blank">ValueListenableProvider</a></li><li><a href="https://pub.dev/documentation/provider/latest/provider/StreamProvider-class.html" rel="noreferrer noopener" target="_blank">StreamProvider</a></li><li><a href="https://pub.dev/documentation/provider/latest/provider/FutureProvider-class.html" rel="noreferrer noopener" target="_blank">FutureProvider</a></li></ul>
<!-- /wp:list -->

<!-- wp:paragraph -->
<p>Now we will use a <strong>Selector</strong>.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>In this approach, we have <strong>ChangeNotifierProvider</strong> at the top, followed by our UI.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>So, for adding values to our model (ChangeNotifier model, UserData) we use</p>
<!-- /wp:paragraph -->

<!-- wp:quote -->
<blockquote class="wp-block-quote"><p>context.read&lt;UserData&gt;()</p></blockquote>
<!-- /wp:quote -->

<!-- wp:image -->
<figure class="wp-block-image"><img src="https://cdn-images-1.medium.com/max/1600/1*REmoM0OXTqsK1MR8ijlDcw.png" alt="Using Selector in Provider"/><figcaption>Using Selector in Provider</figcaption></figure>
<!-- /wp:image -->

<!-- wp:paragraph -->
<p>This is an extension included in Provider, now we have the input inside our model(UserData).</p>
<!-- /wp:paragraph -->

<!-- wp:heading {"level":3} -->
<h3>NotifyListeners</h3>
<!-- /wp:heading -->

<!-- wp:quote -->
<blockquote class="wp-block-quote"><p>Note: Setting of the value, notifies the model since the setter implements notifyListeners.</p></blockquote>
<!-- /wp:quote -->

<!-- wp:preformatted -->
<pre class="wp-block-preformatted">set emailAddress(String emailAddress) {<br>   _emailAddress = emailAddress;<br>   notifyListeners();<br>}</pre>
<!-- /wp:preformatted -->

<!-- wp:preformatted -->
<pre class="wp-block-preformatted">// SIMILAR FOR NAME AND AGE</pre>
<!-- /wp:preformatted -->

<!-- wp:paragraph -->
<p>Similarly, we do this for all the input fields (name, age, and email)</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>Let's say, we want to display the values entered in these fields in real-time.</p>
<!-- /wp:paragraph -->

<!-- wp:image -->
<figure class="wp-block-image"><img src="https://cdn-images-1.medium.com/max/1600/1*5yPj18JiKrdwMXk85FQK9A.png" alt="Selector in Provider"/><figcaption>Selector in Provider</figcaption></figure>
<!-- /wp:image -->

<!-- wp:list -->
<ul><li>Email Text should only listen to Email Field.</li><li>Name + Age Text should only listen to changes in Name and Age Fields</li><li>For displaying all values of the form, we need to listen to every field</li></ul>
<!-- /wp:list -->

<!-- wp:heading {"level":4} -->
<h4><strong>Email Text</strong></h4>
<!-- /wp:heading -->

<!-- wp:preformatted -->
<pre class="wp-block-preformatted">final _email =
context.select&lt;UserData, String>((model) => model.emailAddress);
return Text('(Listen to Email) Email : $_email');</pre>
<!-- /wp:preformatted -->

<!-- wp:paragraph -->
<p>We use <strong>context.select</strong>.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>As per documentation</p>
<!-- /wp:paragraph -->

<!-- wp:quote -->
<blockquote class="wp-block-quote"><p>Watch a value of type [T] exposed from a provider, and listen only partially to changes.&nbsp;</p></blockquote>
<!-- /wp:quote -->

<!-- wp:quote -->
<blockquote class="wp-block-quote"><p>By using [select], instead of watching the entire object, the listener will rebuild only if the value returned by <code>selector</code> changes.</p></blockquote>
<!-- /wp:quote -->

<!-- wp:paragraph -->
<p>Hence for email text, we select only the email field and get notified when it changes.&nbsp;</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p><strong>Name + Age Text</strong></p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>Here, we want to listen to two fields from our notifier model.&nbsp;</p>
<!-- /wp:paragraph -->

<!-- wp:quote -->
<blockquote class="wp-block-quote"><p>Time to introduce a new package <a href="https://pub.dev/packages/tuple" rel="noreferrer noopener" target="_blank"><strong>tuple</strong></a>.</p></blockquote>
<!-- /wp:quote -->

<!-- wp:paragraph -->
<p>This package gives us options to select the number of values and comes recommended by Provider. Currently supports 7 values.</p>
<!-- /wp:paragraph -->

<!-- wp:quote -->
<blockquote class="wp-block-quote"><p>To select multiple values without having to write a class that implements <code>==</code>, the easiest solution is to use a "Tuple" from <a href="https://pub.dev/packages/tuple" rel="noreferrer noopener" target="_blank">tuple</a></p></blockquote>
<!-- /wp:quote -->

<!-- wp:paragraph -->
<p>Since we need 2 fields, we use <strong>Tuple2</strong></p>
<!-- /wp:paragraph -->

<!-- wp:image -->
<figure class="wp-block-image"><img src="https://cdn-images-1.medium.com/max/1600/1*XNlThb4zwlHuEw9FInxZ6g.png" alt="Tuple2 example"/><figcaption>Tuple2 example</figcaption></figure>
<!-- /wp:image -->

<!-- wp:paragraph -->
<p>Here, we use the <strong>Selector</strong> widget</p>
<!-- /wp:paragraph -->

<!-- wp:quote -->
<blockquote class="wp-block-quote"><p>An equivalent to [Consumer] that can filter updates by selecting a limited amount of values and prevent rebuild if they don’t change.</p></blockquote>
<!-- /wp:quote -->

<!-- wp:paragraph -->
<p>Criteria: Tuple2 of Name field and age field, <strong>Tuple2&lt;String, int&gt;.</strong></p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>Hence, inside our builder, we can retrieve these values by </p>
<!-- /wp:paragraph -->

<!-- wp:preformatted -->
<pre class="wp-block-preformatted">data.item1 // For name, since First value of Tuple is String

data.item2 // For age, since Second value of Tuple is int</pre>
<!-- /wp:preformatted -->

<!-- wp:paragraph -->
<p><strong>All Text</strong></p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>Here, we need to listen to all the values inside our notifier model. This turns out to be a good use-case for <strong>Consumer</strong>.</p>
<!-- /wp:paragraph -->

<!-- wp:preformatted -->
<pre class="wp-block-preformatted">Consumer&lt;UserData>(
  builder: (_, data, __) {
    return Text(
          '(Listening to all) Name : ${data.name} >>> Age : ${data.age} >>> Email${data.emailAddress}',
    );
  },
);</pre>
<!-- /wp:preformatted -->

*In case it helped :)*
<a href="https://www.buymeacoffee.com/aseemwangoo" target="_blank"><img src="https://www.buymeacoffee.com/assets/img/custom_images/orange_img.png" alt="Pass Me A Coffee!!" style="height: 41px !important;width: 174px !important;box-shadow: 0px 3px 2px 0px rgba(190, 190, 190, 0.5) !important;-webkit-box-shadow: 0px 3px 2px 0px rgba(190, 190, 190, 0.5) !important;" ></a>

{% youtube bYQJp8XQd6U %}

<!-- wp:quote -->
<blockquote class="wp-block-quote"><p>Hosted URL&nbsp;: <a href="https://web.flatteredwithflutter.com/#/" rel="noreferrer noopener" target="_blank">https://web.flatteredwithflutter.com/#/</a></p></blockquote>
<!-- /wp:quote -->

<!-- wp:quote -->
<blockquote class="wp-block-quote"><p><a href="https://github.com/AseemWangoo/experiments_with_web" rel="noreferrer noopener" target="_blank">Source code for Flutter Web App..</a></p></blockquote>
<!-- /wp:quote -->