<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Pedro Massango</title>
    <description>The latest articles on DEV Community by Pedro Massango (@pedromassango).</description>
    <link>https://dev.to/pedromassango</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F196272%2Ff58e3df9-1f0d-479d-b5ea-e0bfe36df063.png</url>
      <title>DEV Community: Pedro Massango</title>
      <link>https://dev.to/pedromassango</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/pedromassango"/>
    <language>en</language>
    <item>
      <title>Too busy for friends? Try Friendship 1:1s</title>
      <dc:creator>Pedro Massango</dc:creator>
      <pubDate>Fri, 26 Sep 2025 00:10:04 +0000</pubDate>
      <link>https://dev.to/pedromassango/too-busy-for-friends-try-friendship-11s-g5d</link>
      <guid>https://dev.to/pedromassango/too-busy-for-friends-try-friendship-11s-g5d</guid>
      <description>&lt;p&gt;When I moved to Germany, I quickly realized how easy it was to lose touch with people who mattered to me. Between new personal responsibilities, career demands, and adjusting to a new culture, staying connected fell by the wayside.&lt;/p&gt;

&lt;p&gt;Months would slip by without a real conversation. At best, I’d exchange a few short messages over social media — nothing like the deep talks we used to have.&lt;/p&gt;

&lt;p&gt;That's when I decided to bring a professional practice into my personal life: &lt;strong&gt;1:1s&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  1:1s
&lt;/h3&gt;

&lt;p&gt;In a work environment, 1:1s are regular check-ins between a manager and a direct report, or between colleagues, to catch up. &lt;/p&gt;

&lt;p&gt;I adapted this idea into Friendship 1:1s.&lt;/p&gt;

&lt;h3&gt;
  
  
  Friendship 1:1s
&lt;/h3&gt;

&lt;p&gt;Intentional 30/60 minute catch-ups with friends or family, scheduled just like any important meeting.&lt;/p&gt;

&lt;p&gt;The impact has been incredible. Each month, I aim for at least three Friendship 1:1s. These conversations help me feel more grounded, closer to the people I care about, and better balanced in life.&lt;/p&gt;

&lt;p&gt;If you’ve been struggling to find time for meaningful connections, give this a try. A simple scheduled 1:1 could be the difference between not keeping deeper connection with people and staying close enought to have meaniful friendships.&lt;/p&gt;

&lt;h3&gt;
  
  
  Make use of your Caleandar
&lt;/h3&gt;

&lt;p&gt;One thing that can drastically improve this is by opening some slots on your Calendar (free on Google calendar), and then send the link to the people you want to have 1:1 with. This helps keep track of when was the last time you spoke to someone and avoids events onverlaps.&lt;/p&gt;

&lt;p&gt;If you’ve been struggling to find time for meaningful connections, give this a try. A simple scheduled 1:1 could be exactly the thing you need to reignite the spark of friendship with the people you love and admire. &lt;/p&gt;

</description>
      <category>personal</category>
      <category>life</category>
    </item>
    <item>
      <title>Scrolling like a Pro - Creating custom scroll behaviors</title>
      <dc:creator>Pedro Massango</dc:creator>
      <pubDate>Mon, 07 Jul 2025 19:35:19 +0000</pubDate>
      <link>https://dev.to/pedromassango/scrolling-like-a-pro-creating-custom-scroll-behaviors-29e9</link>
      <guid>https://dev.to/pedromassango/scrolling-like-a-pro-creating-custom-scroll-behaviors-29e9</guid>
      <description>&lt;p&gt;Hi there, long time no see, today I have decided to share some common tips and tricks on scrolling with Flutter&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Customize Scroll Behavior in Flutter?
&lt;/h2&gt;

&lt;p&gt;Flutter gives you powerful out of the box scroll widgets like &lt;code&gt;ListView&lt;/code&gt;, &lt;code&gt;SingleChildScrollView&lt;/code&gt;, and &lt;code&gt;PageView&lt;/code&gt;. But sometimes, you need &lt;strong&gt;custom scroll effects&lt;/strong&gt; to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Remove glow on overscroll (Android)&lt;/li&gt;
&lt;li&gt;Customize scroll physics (bouncy, clamped, paged)&lt;/li&gt;
&lt;li&gt;Trigger animations or data loads when scrolling&lt;/li&gt;
&lt;li&gt;Create sticky headers, parallax, or infinite scroll&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let’s see some real code life examples below:&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Remove Overscroll Glow (Android Ripple)
&lt;/h2&gt;

&lt;p&gt;By default, Android shows a glow effect on overscroll and not every company's design system follow this behavior so there is always a need to get rid of it. To remove it, override the scroll behavior globally:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;NoGlowScrollBehavior&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="n"&gt;ScrollBehavior&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nd"&gt;@override&lt;/span&gt;
  &lt;span class="n"&gt;Widget&lt;/span&gt; &lt;span class="n"&gt;buildViewportChrome&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;BuildContext&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;Widget&lt;/span&gt; &lt;span class="n"&gt;child&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;AxisDirection&lt;/span&gt; &lt;span class="n"&gt;axisDirection&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;child&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then apply it globally:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="n"&gt;MaterialApp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nl"&gt;scrollBehavior:&lt;/span&gt; &lt;span class="n"&gt;NoGlowScrollBehavior&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="nl"&gt;home:&lt;/span&gt; &lt;span class="n"&gt;MyHomePage&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or locally:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="n"&gt;ScrollConfiguration&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nl"&gt;behavior:&lt;/span&gt; &lt;span class="n"&gt;NoGlowScrollBehavior&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="nl"&gt;child:&lt;/span&gt; &lt;span class="n"&gt;ListView&lt;/span&gt;&lt;span class="p"&gt;(...),&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  2. Listen to Scroll Position
&lt;/h2&gt;

&lt;p&gt;Track scroll position or trigger logic on scroll, there are different ways to achieve this and below I will share the implementation using a &lt;code&gt;ScrollController&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;_controller&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ScrollController&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="nd"&gt;@override&lt;/span&gt;
&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;initState&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;initState&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="n"&gt;_controller&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;addListener&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_controller&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;offset&lt;/span&gt; &lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'Scrolled past 100 pixels'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nd"&gt;@override&lt;/span&gt;
&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;dispose&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;_controller&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;dispose&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;dispose&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Usage:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="n"&gt;ListView&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nl"&gt;controller:&lt;/span&gt; &lt;span class="n"&gt;_controller&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nl"&gt;children:&lt;/span&gt; &lt;span class="p"&gt;[...],&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  3. Custom Scroll Physics (e.g., Bouncing like iOS)
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="n"&gt;ListView&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nl"&gt;physics:&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;BouncingScrollPhysics&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="c1"&gt;// or NeverScrollableScrollPhysics()&lt;/span&gt;
  &lt;span class="nl"&gt;children:&lt;/span&gt; &lt;span class="p"&gt;[...],&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can also combine physics:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="nl"&gt;physics:&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;BouncingScrollPhysics&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nl"&gt;parent:&lt;/span&gt; &lt;span class="n"&gt;AlwaysScrollableScrollPhysics&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  4. Scroll to a Widget programmatically
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="n"&gt;_scrollController&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;animateTo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="mf"&gt;500.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// offset&lt;/span&gt;
  &lt;span class="nl"&gt;duration:&lt;/span&gt; &lt;span class="n"&gt;Duration&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;milliseconds:&lt;/span&gt; &lt;span class="mi"&gt;400&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="nl"&gt;curve:&lt;/span&gt; &lt;span class="n"&gt;Curves&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;easeInOut&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or scroll to a widget using &lt;code&gt;Scrollable.ensureVisible&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="n"&gt;Scrollable&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ensureVisible&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nl"&gt;duration:&lt;/span&gt; &lt;span class="n"&gt;Duration&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;milliseconds:&lt;/span&gt; &lt;span class="mi"&gt;300&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="nl"&gt;alignment:&lt;/span&gt; &lt;span class="mf"&gt;0.5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  5. Advanced: create a sticky header or a parallax effect
&lt;/h2&gt;

&lt;p&gt;Use &lt;code&gt;CustomScrollView&lt;/code&gt; + &lt;code&gt;SliverPersistentHeader&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="n"&gt;SliverPersistentHeader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nl"&gt;pinned:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nl"&gt;delegate:&lt;/span&gt; &lt;span class="n"&gt;MyHeaderDelegate&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
&lt;span class="p"&gt;),&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or use packages like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://pub.dev/packages/flutter_sticky_header" rel="noopener noreferrer"&gt;&lt;code&gt;flutter_sticky_header&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://pub.dev/packages/parallax" rel="noopener noreferrer"&gt;&lt;code&gt;parallax&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Task&lt;/th&gt;
&lt;th&gt;Tool/Widget&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Remove glow&lt;/td&gt;
&lt;td&gt;&lt;code&gt;ScrollBehavior&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Track scroll&lt;/td&gt;
&lt;td&gt;&lt;code&gt;ScrollController&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Customize physics&lt;/td&gt;
&lt;td&gt;&lt;code&gt;ScrollPhysics&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Animate to scroll&lt;/td&gt;
&lt;td&gt;&lt;code&gt;ScrollController.animateTo()&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Sticky/parallax effects&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;CustomScrollView&lt;/code&gt;, &lt;code&gt;Sliver&lt;/code&gt; widgets&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Bonus: infinite scroll example
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="n"&gt;_controller&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;addListener&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_controller&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;position&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;pixels&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt;
      &lt;span class="n"&gt;_controller&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;position&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;maxScrollExtent&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;fetchMoreItems&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Flutter gives you the flexibility to &lt;strong&gt;tune every aspect of scrolling&lt;/strong&gt; — whether it's subtle UX improvements or complex scroll-driven required by your company's UX, you're pretty much set to implement everything with Flutter.&lt;/p&gt;

</description>
      <category>flutter</category>
      <category>webdev</category>
    </item>
    <item>
      <title>The beginer mindset</title>
      <dc:creator>Pedro Massango</dc:creator>
      <pubDate>Sun, 02 Mar 2025 22:43:56 +0000</pubDate>
      <link>https://dev.to/pedromassango/the-beginer-mindset-2e7i</link>
      <guid>https://dev.to/pedromassango/the-beginer-mindset-2e7i</guid>
      <description>&lt;p&gt;Recently I started learning something... again. It is always scary to  jump on a new topic a feel like you know nothing about it.&lt;/p&gt;

&lt;p&gt;I will ocasionaly share my learnings along the way here. The topics range from basic Kotlin to advanced and might touch some Spring boot or Ktor, my end goal is to become a proficient Kotlin developer by the end of this year or sooner.&lt;/p&gt;

&lt;p&gt;Follow me if you want to follow my journey.&lt;/p&gt;

</description>
      <category>kotlin</category>
      <category>springboot</category>
      <category>beginners</category>
      <category>learning</category>
    </item>
    <item>
      <title>Announcing the Public Beta of doc-ai</title>
      <dc:creator>Pedro Massango</dc:creator>
      <pubDate>Thu, 07 Sep 2023 16:25:56 +0000</pubDate>
      <link>https://dev.to/pedromassango/announcing-the-public-beta-of-doc-ai-1c8n</link>
      <guid>https://dev.to/pedromassango/announcing-the-public-beta-of-doc-ai-1c8n</guid>
      <description>&lt;p&gt;I'm thrilled to introduce the public beta of &lt;a href="https://doc-ai.app" rel="noopener noreferrer"&gt;doc-ai&lt;/a&gt;, a groundbreaking AI-powered platform designed to deeply understand and process the contents of your documents. Say goodbye to the days of endlessly skimming through pages to find that one piece of information. Now, you can simply ask a question and get precise, contextual answers directly from the text!&lt;/p&gt;

&lt;h3&gt;
  
  
  How Does It Work?
&lt;/h3&gt;

&lt;p&gt;At its core, &lt;a href="https://doc-ai.app" rel="noopener noreferrer"&gt;doc-ai.app&lt;/a&gt; leverages cutting-edge artificial intelligence to read and interpret documents just like a human would, but at lightning speed. Whether you have lengthy &lt;strong&gt;research papers&lt;/strong&gt;, detailed reports, or &lt;strong&gt;comprehensive manuals&lt;/strong&gt;, our AI can digest the content and provide you with answers in seconds.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why Use doc-ai.app?
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Save Time&lt;/strong&gt;: No more manual searching. Get the information you need instantly.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Increase Accuracy&lt;/strong&gt;: Receive answers that are contextually relevant, reducing the risk of misinterpretation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;User-Friendly&lt;/strong&gt;: Designed for everyone, from students to professionals. &lt;strong&gt;No technical expertise required&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;I invite you to try it out and experience firsthand the power of AI-driven document comprehension. Try out the public beta of &lt;a href="https://doc-ai.app" rel="noopener noreferrer"&gt;doc-ai.app&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Discount:&lt;/strong&gt; 20% off for the first 15 to upgrade to premium using the following discount code: &lt;strong&gt;PUBLICB&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Let me know your feedback!&lt;/p&gt;

</description>
      <category>ai</category>
      <category>document</category>
      <category>news</category>
      <category>buildinpublic</category>
    </item>
    <item>
      <title>Dart for backend: pros and cons</title>
      <dc:creator>Pedro Massango</dc:creator>
      <pubDate>Mon, 03 Apr 2023 17:54:58 +0000</pubDate>
      <link>https://dev.to/pedromassango/dart-for-backend-pros-and-cons-2jh</link>
      <guid>https://dev.to/pedromassango/dart-for-backend-pros-and-cons-2jh</guid>
      <description>&lt;p&gt;Dart is an object-oriented, class-based, garbage-collected programming language developed by Google. Initially designed for client-side development, Dart has evolved to become a full-stack language that can run on the backend as well. This short article explores the benefits and drawbacks of using Dart for backend development.&lt;/p&gt;

&lt;p&gt;Advantages of using Dart for Backend Development:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Single Language for Full-Stack Development (specially when using Flutter for front-end)&lt;/li&gt;
&lt;li&gt;Speed and Performance&lt;/li&gt;
&lt;li&gt;Scalability&lt;/li&gt;
&lt;li&gt;Built-in Support for Asynchronous Programming&lt;/li&gt;
&lt;li&gt;Strong Typing&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Disadvantages of using Dart for Backend Development:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Lack of Third-Party Libraries&lt;/li&gt;
&lt;li&gt;Limited Community Support&lt;/li&gt;
&lt;li&gt;Lack of Maturity&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Those are very important things to consider, specially if you   're new to Dart and want a fast solution to build and deliver your project as it is likely that you will have to build some third-party libraries yourself.&lt;/p&gt;

&lt;p&gt;Dart is a great option for backend development, particularly for developers who already use it for front-end development. Its speed, scalability, and support for asynchronous programming make it an attractive choice. However, it's important to consider the potential drawbacks, such as the limited third-party library support and smaller community. Despite these challenges, Google's continued investment in Dart suggests that it will continue to grow and evolve over time.&lt;/p&gt;

&lt;p&gt;It is relatively easy to learn Dart so if time is not against you, then it is definitely worth a try.&lt;/p&gt;

</description>
      <category>dart</category>
      <category>flutter</category>
      <category>backend</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Double click listener on Android</title>
      <dc:creator>Pedro Massango</dc:creator>
      <pubDate>Thu, 22 Dec 2022 10:39:26 +0000</pubDate>
      <link>https://dev.to/pedromassango/double-click-listener-on-android-f0j</link>
      <guid>https://dev.to/pedromassango/double-click-listener-on-android-f0j</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjlo5ht51unltxu7efjto.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjlo5ht51unltxu7efjto.jpeg" alt="cover" width="600" height="315"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Some times we need to check when the user made a double click in some of our android views. To solve this problem I made a small library to handle this.&lt;br&gt;
How to use?&lt;br&gt;
Using Android Studio, just add this line in your build.gradle project level:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;allprojects {
    repositories {
        ...
        maven { url 'https://jitpack.io' } // add this line
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Second, add this line inside dependencies on your app build.gradle module level:&lt;br&gt;
&lt;code&gt;implementation 'com.github.pedromassango:doubleClick:v3.0'&lt;/code&gt;&lt;br&gt;
The class DoubleClick extends from View.OnClickListener so, just call the DoubleClick class on you onClickListener of the view that you wish to listen, and pass a instance of DoubleClickListener class to listen the events.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nc"&gt;Button&lt;/span&gt; &lt;span class="n"&gt;btn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Button&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;btn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setOnClickListener&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;DoubleClick&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;DoubleClickListener&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="nd"&gt;@Override&lt;/span&gt;
            &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;onSingleClick&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;View&lt;/span&gt; &lt;span class="n"&gt;view&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

                &lt;span class="c1"&gt;// Single tap here.&lt;/span&gt;
            &lt;span class="o"&gt;}&lt;/span&gt;

            &lt;span class="nd"&gt;@Override&lt;/span&gt;
            &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;onDoubleClick&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;View&lt;/span&gt; &lt;span class="n"&gt;view&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

                &lt;span class="c1"&gt;// Double tap here.&lt;/span&gt;
            &lt;span class="o"&gt;}&lt;/span&gt;
        &lt;span class="o"&gt;});&lt;/span&gt;
        &lt;span class="c1"&gt;//  use this to define your own interval&lt;/span&gt;
        &lt;span class="c1"&gt;//  }, 100));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;OBS: On the latest version you can define your own interval!&lt;br&gt;
To know more, check it on GitHub:&lt;br&gt;
&lt;a href="https://github.com/pedromassango/doubleClick" rel="noopener noreferrer"&gt;https://github.com/pedromassango/doubleClick&lt;/a&gt;&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Evite o padrão de repositório para operações não relacionadas à persistência</title>
      <dc:creator>Pedro Massango</dc:creator>
      <pubDate>Fri, 02 Jul 2021 23:02:37 +0000</pubDate>
      <link>https://dev.to/pedromassango/evite-o-padrao-de-repositorio-para-operacoes-nao-relacionadas-a-persistencia-5d8a</link>
      <guid>https://dev.to/pedromassango/evite-o-padrao-de-repositorio-para-operacoes-nao-relacionadas-a-persistencia-5d8a</guid>
      <description>&lt;p&gt;English version available &lt;a href="https://dev.to/pedromassango/avoid-repository-pattern-for-operations-not-related-to-persistence-5gng"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Hoje quero compartilhar um pouco sobre o padrão Repositório e Fachada. Tentarei explicar suas diferenças, pois parece haver alguns equívocos comuns sobre eles.&lt;/p&gt;

&lt;h2&gt;
  
  
  Repositório
&lt;/h2&gt;

&lt;p&gt;Vamos tentar definir um repositório, a partir do dicionário: &lt;strong&gt;um lugar, sala ou contêiner onde algo é depositado ou armazenado&lt;/strong&gt;. Em termos de programação, o conceito pode ser definido como uma classe responsável por lidar com operações CRUD (criar, ler, atualizar e deletar) para um modelo de domínio específico por meio do uso de uma ou mais fontes de dados.&lt;/p&gt;

&lt;p&gt;Pela definição acima, podemos ver que devemos usar repositórios apenas para operações CRUD, o que significa que podemos ter um &lt;code&gt;UserRepository&lt;/code&gt; e nunca um&lt;code&gt;AuthenticationRepository&lt;/code&gt;, simplesmente porque a autenticação não descreve um conjunto de operações CRUD (assumindo que estamos falando sobre operações de login/registro).&lt;/p&gt;

&lt;p&gt;Um erro comum que tenho visto é que algumas pessoas definem repositórios para operações de acesso ao sistema por exemplo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kd"&gt;abstract&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AuthenticationRepository&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="n"&gt;Future&lt;/span&gt; &lt;span class="n"&gt;login&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="n"&gt;Future&lt;/span&gt; &lt;span class="n"&gt;register&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Resumo #1: Apenas use o padrão de repositório para operações CRUD
&lt;/h4&gt;

&lt;p&gt;Claramente, essas não são operações para armazenar/recuperar dados e, portanto, nunca devemos declará-las em um repositório. E agora? Fachadas!&lt;/p&gt;

&lt;h2&gt;
  
  
  Fachadas / Facade pattern
&lt;/h2&gt;

&lt;p&gt;Pela Wikipedia, podemos definir uma fachada como &lt;strong&gt;um objeto que serve como uma interface frontal mascarando um código subjacente mais complexo&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Agora vamos definir um repositório: um Repositório é um tipo de fachada especializada em mascarar/abstrair operações CRUD complexas especificamente entre fontes de dados.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3povfaqu6g7npnyt8akm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3povfaqu6g7npnyt8akm.png" alt="Repository é um tipo mais especializado de Facade" width="800" height="439"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Para comparar e contrastar, fachadas são mais gerais do que repositórios - eles podem ser usados para qualquer coisa diferente de persistência. Você pode usar fachadas para abstrair interações complexas em APIs de vários bancos. Por exemplo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Or BankOperationsFacade.&lt;/span&gt;
&lt;span class="kd"&gt;abstract&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;BankOperations&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="n"&gt;Future&lt;/span&gt; &lt;span class="n"&gt;payTelecomService&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="n"&gt;cardId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="n"&gt;serviceId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="n"&gt;Future&lt;/span&gt; &lt;span class="n"&gt;transfer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="n"&gt;senderId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="n"&gt;recipientId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Custom implementation for XBank interaction goes here.&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;XBankOperations&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="n"&gt;BankOperations&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Custom implementation for YBank interaction goes here.&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;YBankBOperations&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="n"&gt;BankOperations&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Resumo #2: Repository é um tipo mais especializado de Facade
&lt;/h4&gt;

&lt;p&gt;Vamos revisar o primeiro trecho de código apresentado em nosso artigo, mas, desta vez, iremos refatorar o nome da classe para ser algo mais significativo.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Or any other meaningful name.&lt;/span&gt;
&lt;span class="kd"&gt;abstract&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AuthenticationFacade&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="n"&gt;Future&lt;/span&gt; &lt;span class="n"&gt;login&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="n"&gt;Future&lt;/span&gt; &lt;span class="n"&gt;register&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Principais conclusões
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;As fachadas podem ser aplicadas a qualquer coisa que não seja baseada na persistência&lt;/li&gt;
&lt;li&gt;Repositórios são para envolver a comunicação com uma ou mais fontes de dados e abstrair isso do usuário do repositório&lt;/li&gt;
&lt;li&gt;Fachadas são mais genéricas do que repositórios.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;É importante fazer uso desses conceitos de maneira adequada para evitar escrever códigos difíceis de entender e para manter uma base de código saudável.&lt;/p&gt;

&lt;p&gt;Espero que isso ajude você de alguma forma; por favor, deixe-me saber sua opinião na seção de comentários.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>dart</category>
      <category>architecture</category>
    </item>
    <item>
      <title>Avoid Repository pattern for operations not related to persistence</title>
      <dc:creator>Pedro Massango</dc:creator>
      <pubDate>Fri, 02 Jul 2021 23:01:24 +0000</pubDate>
      <link>https://dev.to/pedromassango/avoid-repository-pattern-for-operations-not-related-to-persistence-5gng</link>
      <guid>https://dev.to/pedromassango/avoid-repository-pattern-for-operations-not-related-to-persistence-5gng</guid>
      <description>&lt;p&gt;Versão em Portugês disponível &lt;a href="https://dev.to/pedromassango/evite-o-padrao-de-repositorio-para-operacoes-nao-relacionadas-a-persistencia-5d8a"&gt;aqui&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Today I want to share a bit about the Repository and Facade pattern. I will attempt to explain their differences, as there seems to be a few common misconceptions about them. &lt;/p&gt;

&lt;h2&gt;
  
  
  Repository
&lt;/h2&gt;

&lt;p&gt;Let's try to define a repository, from the dictionary: &lt;strong&gt;a place, room or container where something is deposited or stored&lt;/strong&gt;. Interms of programming, the concept can be defined as a class responsible for handling CRUD (create, read, update and delete) operations for a specific domain model through the usage of one or more data sources.&lt;/p&gt;

&lt;p&gt;By the definition above, we can see that we should use repositories for CRUD operations only, which means we can have a &lt;code&gt;UserRepository&lt;/code&gt; and never a &lt;code&gt;AuthenticationRepository&lt;/code&gt;, simply because authentication does not describe a set of CRUD operations (assuming we're talking about login/registration operations).&lt;/p&gt;

&lt;p&gt;A common mistake I have seen is that some people define repositories for system access operations for example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kd"&gt;abstract&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AuthenticationRepository&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="n"&gt;Future&lt;/span&gt; &lt;span class="n"&gt;login&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="n"&gt;Future&lt;/span&gt; &lt;span class="n"&gt;register&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Take #1: Only use repository pattern for CRUD operations
&lt;/h4&gt;

&lt;p&gt;Clearly those are not operations for storing/retrieving data and so we should never declare them in a repository. Then what? Facades!&lt;/p&gt;

&lt;h2&gt;
  
  
  Facade pattern
&lt;/h2&gt;

&lt;p&gt;From Wikipedia, we can define a facade as &lt;strong&gt;an object that serves as a front-facing interface masking more complex underlying code&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Now let's move on to defining a repository: a Repository is a type of facade that specializes in masking/abstract complex CRUD operations specifically between data source(s).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3povfaqu6g7npnyt8akm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3povfaqu6g7npnyt8akm.png" alt="A Repository is a more specialized type of Facade" width="800" height="439"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To compare and constrast, facades are more general than repositories -- they can be used for anything other than persistence. You can use facades to abstract complex interactions within  multiple bank APIs. For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Or BankOperationsFacade.&lt;/span&gt;
&lt;span class="kd"&gt;abstract&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;BankOperations&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="n"&gt;Future&lt;/span&gt; &lt;span class="n"&gt;payTelecomService&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="n"&gt;cardId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="n"&gt;serviceId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="n"&gt;Future&lt;/span&gt; &lt;span class="n"&gt;transfer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="n"&gt;senderId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="n"&gt;recipientId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Custom implementation for XBank interaction goes here.&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;XBankOperations&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="n"&gt;BankOperations&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Custom implementation for YBank interaction goes here.&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;YBankBOperations&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="n"&gt;BankOperations&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Take #2: A Repository is a more specialized type of Facade
&lt;/h4&gt;

&lt;p&gt;Let's review the first piece of code featured in our article, but this time, we'll refactor the name of the class to be something more meaningful.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Or any other meaningful name.&lt;/span&gt;
&lt;span class="kd"&gt;abstract&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AuthenticationFacade&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="n"&gt;Future&lt;/span&gt; &lt;span class="n"&gt;login&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="n"&gt;Future&lt;/span&gt; &lt;span class="n"&gt;register&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Key Takeaways
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Facades can be applied to anything that's not persistence based&lt;/li&gt;
&lt;li&gt;Repositories are for wrapping the communication with one or more data sources and abstracting this away from the user of the repository&lt;/li&gt;
&lt;li&gt;Facades are more generic than repositories. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It is important to make use of those concepts properly to avoid writing code that is hard to understand and to maintain a healthy code base.&lt;/p&gt;

&lt;p&gt;That's it, I hope this helps you somehow; please let me know your thoughts in the comments section.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>dart</category>
      <category>architecture</category>
    </item>
    <item>
      <title>UnconstrainedBox  é seu amigo - Dica #5</title>
      <dc:creator>Pedro Massango</dc:creator>
      <pubDate>Sat, 10 Apr 2021 17:03:08 +0000</pubDate>
      <link>https://dev.to/pedromassango/unconstrainedbox-e-seu-amigo-dica-5-32ph</link>
      <guid>https://dev.to/pedromassango/unconstrainedbox-e-seu-amigo-dica-5-32ph</guid>
      <description>&lt;p&gt;[available in English &lt;a href="https://dev.to/pedromassango/unconstrainedbox-is-your-friend-tip-5-19cl"&gt;here&lt;/a&gt;]&lt;/p&gt;

&lt;p&gt;Olá.&lt;br&gt;
Nesta dica do Flutter, quero falar um pouco sobre o widget &lt;code&gt;UnconstrainedBox&lt;/code&gt;, você já o usou antes? Me conte nos comentários.&lt;/p&gt;
&lt;h3&gt;
  
  
  Para que serve?
&lt;/h3&gt;

&lt;p&gt;Resumindo, é um widget que dá ao filho a liberdade de se dimensionar conforme necessário. &lt;code&gt;UnconstrainedBox&lt;/code&gt; (como o nome sugere), não impõe restrições ao seu filho, o filho irá renderizar como se estivesse em uma tela infinita. Às vezes, ele pode transbordar quando usado com alguns widgets como &lt;code&gt;PageView&lt;/code&gt;, então você deve ter cuidado para dar ao filho as restrições de tamanho adequadas, conforme necessário.&lt;/p&gt;
&lt;h3&gt;
  
  
  Aprenda pelo Exemplo
&lt;/h3&gt;

&lt;p&gt;Digamos que precisamos construir um &lt;code&gt;PageView&lt;/code&gt; onde seus filhos têm tamanhos diferentes e deve mostrar um item por vez, como você faria isso? (Deixe-me saber nos comentários).&lt;/p&gt;

&lt;p&gt;Aqui está nosso código inicial, é apenas um &lt;code&gt;PageView&lt;/code&gt; com três itens: um contêiner vermelho, verde e azul.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="s"&gt;'package:flutter/material.dart'&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;runApp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;MaterialApp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;home:&lt;/span&gt; &lt;span class="n"&gt;UnconstrainedBoxSample&lt;/span&gt;&lt;span class="p"&gt;()));&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UnconstrainedBoxSample&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="n"&gt;StatelessWidget&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="nd"&gt;@override&lt;/span&gt;
  &lt;span class="n"&gt;Widget&lt;/span&gt; &lt;span class="n"&gt;build&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BuildContext&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;Scaffold&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="nl"&gt;backgroundColor:&lt;/span&gt; &lt;span class="n"&gt;Colors&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;white&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nl"&gt;appBar:&lt;/span&gt; &lt;span class="n"&gt;AppBar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;title:&lt;/span&gt; &lt;span class="n"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'Unconstrained Box'&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
      &lt;span class="nl"&gt;body:&lt;/span&gt; &lt;span class="n"&gt;PageView&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nl"&gt;children:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
          &lt;span class="n"&gt;Container&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;color:&lt;/span&gt; &lt;span class="n"&gt;Colors&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;red&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
          &lt;span class="n"&gt;Container&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;color:&lt;/span&gt; &lt;span class="n"&gt;Colors&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;green&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
          &lt;span class="n"&gt;Container&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;color:&lt;/span&gt; &lt;span class="n"&gt;Colors&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;blue&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="p"&gt;],&lt;/span&gt;
      &lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Aqui está a saída do código acima.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyqhuquhvb9ezk9hv6urf.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyqhuquhvb9ezk9hv6urf.gif" alt="GIF #1" width="294" height="638"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Como você pode ver, todos os três itens estão sendo expandidos para caber na página inteira, definir um tamanho personalizado para nossos filhos não funciona porque o &lt;code&gt;PageView&lt;/code&gt; força-os a terem o mesmo tamanho (na direção de não rolagem) que ele.&lt;/p&gt;

&lt;p&gt;Podemos contornar isso alterando a janela de visualização da página, mas isso teria um efeito colateral: outros itens também seriam exibidos e nossos filhos ainda seriam forçados a ter a mesma altura da &lt;code&gt;PageView&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Vamos tentar isso, adicionar um controlador com uma fração de porta de visualização personalizada em sua visualização de página: &lt;code&gt;controller: PageController (viewportFraction: .8)&lt;/code&gt; e o resultado é o seguinte.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7h1jvv03kl7m13q1bahd.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7h1jvv03kl7m13q1bahd.gif" alt="GIF #2" width="294" height="638"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Isso acontece porque &lt;code&gt;PageView&lt;/code&gt; está impondo restrições para seus filhos. O padrão (&lt;code&gt;viewportFraction: 1&lt;/code&gt;) significa que cada filho deve ter exatamente o mesmo tamanho de seu pai (o &lt;code&gt;PageView&lt;/code&gt;). Cada vez que você diminui o &lt;code&gt;viewportFraction&lt;/code&gt;, você está apenas diminuindo o tamanho de seus filhos.&lt;/p&gt;

&lt;h2&gt;
  
  
  UnconstrainedBox em ação!
&lt;/h2&gt;

&lt;p&gt;Para resolver os problemas mencionados acima, devemos embrulhar cada criança em uma caixa sem restrições.&lt;/p&gt;

&lt;p&gt;Observe que, embora estejamos usando uma caixa irrestrita, nosso item ainda tem as restrições de: não poder ser maior (em altura/largura dependendo da direção de rolagem) do que o &lt;code&gt;PageView&lt;/code&gt;. A principal vantagem é poder ter filhos menores (em tamanho) que o &lt;code&gt;PageView&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Lembre-se:&lt;/strong&gt; como estamos usando uma caixa sem restrições, nosso filho deve ter tamanho, caso contrário, terá sua largura e altura definidas como zero (&lt;code&gt;0&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Vamos atualizar nosso código, embrulhar seu segundo item em um &lt;code&gt;UnconstrainedBox&lt;/code&gt; e dar ao contêiner um tamanho, nosso código agora se parece com este:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="s"&gt;'package:flutter/material.dart'&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;runApp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;MaterialApp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;home:&lt;/span&gt; &lt;span class="n"&gt;UnconstrainedBoxSample&lt;/span&gt;&lt;span class="p"&gt;()));&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UnconstrainedBoxSample&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="n"&gt;StatelessWidget&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="nd"&gt;@override&lt;/span&gt;
  &lt;span class="n"&gt;Widget&lt;/span&gt; &lt;span class="n"&gt;build&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BuildContext&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;Scaffold&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="nl"&gt;backgroundColor:&lt;/span&gt; &lt;span class="n"&gt;Colors&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;white&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nl"&gt;appBar:&lt;/span&gt; &lt;span class="n"&gt;AppBar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;title:&lt;/span&gt; &lt;span class="n"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'Unconstrained Box'&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
      &lt;span class="nl"&gt;body:&lt;/span&gt; &lt;span class="n"&gt;PageView&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nl"&gt;children:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
          &lt;span class="n"&gt;Container&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;color:&lt;/span&gt; &lt;span class="n"&gt;Colors&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;red&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
          &lt;span class="n"&gt;UnconstrainedBox&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;   &lt;span class="c1"&gt;// NEW&lt;/span&gt;
              &lt;span class="nl"&gt;child:&lt;/span&gt; &lt;span class="n"&gt;Container&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="nl"&gt;height:&lt;/span&gt; &lt;span class="mi"&gt;400&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;// NEW&lt;/span&gt;
                &lt;span class="nl"&gt;width:&lt;/span&gt; &lt;span class="mi"&gt;250&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;   &lt;span class="c1"&gt;// NEW&lt;/span&gt;
                &lt;span class="nl"&gt;color:&lt;/span&gt; &lt;span class="n"&gt;Colors&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;green&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
              &lt;span class="p"&gt;),&lt;/span&gt;
          &lt;span class="p"&gt;),&lt;/span&gt;   &lt;span class="c1"&gt;// NEW&lt;/span&gt;
          &lt;span class="n"&gt;Container&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;color:&lt;/span&gt; &lt;span class="n"&gt;Colors&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;blue&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="p"&gt;],&lt;/span&gt;
      &lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Aqui está o resultado do código acima:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd685esrwhxhe3slqxkim.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd685esrwhxhe3slqxkim.gif" alt="Alt Text" width="294" height="638"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Finalmente, nosso segundo filho agora tem a liberdade de se dimensionar conforme necessário, desde que não ultrapasse o tamanho do PageView. Este widget vem com algumas propriedades úteis como &lt;code&gt;alignment&lt;/code&gt; e &lt;code&gt;constrainedAxis&lt;/code&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;alignment&lt;/code&gt;: permite que você alinhe o filho em seu espaço restante. O padrão é &lt;code&gt;Alignment.center&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;constrainedAxis&lt;/code&gt;: permite especificar um eixo para restringir o filho, ou seja, permite definir em que direção seu widget ainda deve ser restringido. O padrão é &lt;code&gt;null&lt;/code&gt;, o que significa que nenhum dos eixos será restringido.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwppriztr33up3kpzlt7m.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwppriztr33up3kpzlt7m.gif" alt="Alt Text" width="294" height="638"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Este widget nos dá liberdade e a habilidade de construir ótimas animações e UI usando em conjunto com &lt;code&gt;PageView&lt;/code&gt; e outros widgets.&lt;/p&gt;

&lt;p&gt;É tudo por hoje. Curta, compartilhe e inscreva-se para obter mais dicas do Flutter. Comente se você tiver alguma dúvida ou problema.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>UnconstrainedBox is your friend - Tip #5</title>
      <dc:creator>Pedro Massango</dc:creator>
      <pubDate>Sat, 10 Apr 2021 17:02:56 +0000</pubDate>
      <link>https://dev.to/pedromassango/unconstrainedbox-is-your-friend-tip-5-19cl</link>
      <guid>https://dev.to/pedromassango/unconstrainedbox-is-your-friend-tip-5-19cl</guid>
      <description>&lt;p&gt;[Disponível em Português &lt;a href="https://dev.to/pedromassango/unconstrainedbox-is-your-friend-tip-5-19cl"&gt;aqui&lt;/a&gt;]&lt;/p&gt;

&lt;p&gt;Hi there.&lt;br&gt;
In this Flutter tip I want to talk a bit about the &lt;code&gt;UnconstrainedBox&lt;/code&gt; widget, have you ever used it before? Let me know in the comments.&lt;/p&gt;
&lt;h3&gt;
  
  
  What is it for?
&lt;/h3&gt;

&lt;p&gt;In short, it is a widget that gives its child the freedom to size itself as needed. &lt;code&gt;UnconstrainedBox&lt;/code&gt; (as the name suggests), impose no constraints on its child, the child will render as if it were in a infinite canvas. Sometimes it may overflow when used with some widgets like &lt;code&gt;PageView&lt;/code&gt;, so you must be careful to give its child a proper size constraints as required. &lt;/p&gt;
&lt;h3&gt;
  
  
  Learn by Example
&lt;/h3&gt;

&lt;p&gt;Let's say we need to build a &lt;code&gt;PageView&lt;/code&gt; where their children have different sizes and it should show one item at time, how would you do that? (let me know in the comments)&lt;/p&gt;

&lt;p&gt;Here is our initial code, it is just a &lt;code&gt;PageView&lt;/code&gt; with three items: a red, green and blue container.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="s"&gt;'package:flutter/material.dart'&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;runApp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;MaterialApp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;home:&lt;/span&gt; &lt;span class="n"&gt;UnconstrainedBoxSample&lt;/span&gt;&lt;span class="p"&gt;()));&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UnconstrainedBoxSample&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="n"&gt;StatelessWidget&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="nd"&gt;@override&lt;/span&gt;
  &lt;span class="n"&gt;Widget&lt;/span&gt; &lt;span class="n"&gt;build&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BuildContext&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;Scaffold&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="nl"&gt;backgroundColor:&lt;/span&gt; &lt;span class="n"&gt;Colors&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;white&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nl"&gt;appBar:&lt;/span&gt; &lt;span class="n"&gt;AppBar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;title:&lt;/span&gt; &lt;span class="n"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'Unconstrained Box'&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
      &lt;span class="nl"&gt;body:&lt;/span&gt; &lt;span class="n"&gt;PageView&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nl"&gt;children:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
          &lt;span class="n"&gt;Container&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;color:&lt;/span&gt; &lt;span class="n"&gt;Colors&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;red&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
          &lt;span class="n"&gt;Container&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;color:&lt;/span&gt; &lt;span class="n"&gt;Colors&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;green&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
          &lt;span class="n"&gt;Container&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;color:&lt;/span&gt; &lt;span class="n"&gt;Colors&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;blue&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="p"&gt;],&lt;/span&gt;
      &lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here is the output of the code above.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyqhuquhvb9ezk9hv6urf.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyqhuquhvb9ezk9hv6urf.gif" alt="GIF #1" width="294" height="638"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you can see all three items are being expanded to fit the entire page, setting a custom size for our children doesn't work because &lt;code&gt;PageView&lt;/code&gt; forces them to have the same size (in the non-scrolling direction) as itself.&lt;/p&gt;

&lt;p&gt;We can work around this by changing the page's viewport but it would have a side effect: other items would be displayed as well and our children would still being forced to have the same height as the &lt;code&gt;PageView&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Let's try that, add a controller with a custom view port fraction into your page view:&lt;br&gt;
&lt;code&gt;controller: PageController(viewportFraction: .8)&lt;/code&gt; and the result is as follow.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7h1jvv03kl7m13q1bahd.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7h1jvv03kl7m13q1bahd.gif" alt="GIF #2" width="294" height="638"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This happens because &lt;code&gt;PageView&lt;/code&gt;is imposing constraints for its children. The default (&lt;code&gt;viewportFraction: 1&lt;/code&gt;) means that each child must have the exact same size as its parent (the &lt;code&gt;PageView&lt;/code&gt;). Each time you decrease the &lt;code&gt;viewportFraction&lt;/code&gt; you are just decreasing the size of its children.&lt;/p&gt;
&lt;h2&gt;
  
  
  UnconstrainedBox in action!
&lt;/h2&gt;

&lt;p&gt;To solve the issues mentioned above, we should wrap each child into a unconstrained box. &lt;/p&gt;

&lt;p&gt;Notice that even though we are using an unconstrained box, our item still have the constraints of: not being able to be bigger (in height/width depending on the scroll direction) than the PageView. The main advantage is to be able to have smaller (in size) children than the &lt;code&gt;PageView&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Remember:&lt;/strong&gt; since we are using a unconstrained box, our child must have size otherwise it will have its width and height set to zero (&lt;code&gt;0&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Let's update our code, wrap your second item into a &lt;code&gt;UnconstrainedBox&lt;/code&gt; and give the container a size, our code now looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="s"&gt;'package:flutter/material.dart'&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;runApp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;MaterialApp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;home:&lt;/span&gt; &lt;span class="n"&gt;UnconstrainedBoxSample&lt;/span&gt;&lt;span class="p"&gt;()));&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UnconstrainedBoxSample&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="n"&gt;StatelessWidget&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="nd"&gt;@override&lt;/span&gt;
  &lt;span class="n"&gt;Widget&lt;/span&gt; &lt;span class="n"&gt;build&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BuildContext&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;Scaffold&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="nl"&gt;backgroundColor:&lt;/span&gt; &lt;span class="n"&gt;Colors&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;white&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nl"&gt;appBar:&lt;/span&gt; &lt;span class="n"&gt;AppBar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;title:&lt;/span&gt; &lt;span class="n"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'Unconstrained Box'&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
      &lt;span class="nl"&gt;body:&lt;/span&gt; &lt;span class="n"&gt;PageView&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nl"&gt;children:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
          &lt;span class="n"&gt;Container&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;color:&lt;/span&gt; &lt;span class="n"&gt;Colors&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;red&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
          &lt;span class="n"&gt;UnconstrainedBox&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;   &lt;span class="c1"&gt;// NEW&lt;/span&gt;
              &lt;span class="nl"&gt;child:&lt;/span&gt; &lt;span class="n"&gt;Container&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="nl"&gt;height:&lt;/span&gt; &lt;span class="mi"&gt;400&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;// NEW&lt;/span&gt;
                &lt;span class="nl"&gt;width:&lt;/span&gt; &lt;span class="mi"&gt;250&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;   &lt;span class="c1"&gt;// NEW&lt;/span&gt;
                &lt;span class="nl"&gt;color:&lt;/span&gt; &lt;span class="n"&gt;Colors&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;green&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
              &lt;span class="p"&gt;),&lt;/span&gt;
          &lt;span class="p"&gt;),&lt;/span&gt;   &lt;span class="c1"&gt;// NEW&lt;/span&gt;
          &lt;span class="n"&gt;Container&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;color:&lt;/span&gt; &lt;span class="n"&gt;Colors&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;blue&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="p"&gt;],&lt;/span&gt;
      &lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here is the output:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd685esrwhxhe3slqxkim.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd685esrwhxhe3slqxkim.gif" alt="Alt Text" width="294" height="638"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Finally our second child now have the freedom to size itself as needed, as long as it does not oversize the PageView's size. This widget comes with some useful properties like &lt;code&gt;alignment&lt;/code&gt; and &lt;code&gt;constrainedAxis&lt;/code&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;alignment&lt;/code&gt;: allows you to align the child in its remaining space. Defaults to &lt;code&gt;Alignment.center&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;constrainedAxis&lt;/code&gt;: you can specify an axis to constrain the child, in other words this allows to  define in which direction your widget should still be constrained. Defaults to &lt;code&gt;null&lt;/code&gt; which means neither axis will be constrained.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwppriztr33up3kpzlt7m.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwppriztr33up3kpzlt7m.gif" alt="Alt Text" width="294" height="638"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This widget gives us freedom and the hability to build great animations and UI using in conjuction with &lt;code&gt;PageView&lt;/code&gt; and other widgets.&lt;/p&gt;

&lt;p&gt;That is it for today. Like share and subscribe for more Flutter tips. Comment if you have any question or issue.&lt;/p&gt;

</description>
      <category>flutter</category>
      <category>flutterdev</category>
      <category>dart</category>
      <category>uiweekly</category>
    </item>
    <item>
      <title>Introduction to State Restoration in Flutter</title>
      <dc:creator>Pedro Massango</dc:creator>
      <pubDate>Mon, 30 Nov 2020 15:07:59 +0000</pubDate>
      <link>https://dev.to/pedromassango/what-is-state-restoration-and-how-to-use-it-in-flutter-5blm</link>
      <guid>https://dev.to/pedromassango/what-is-state-restoration-and-how-to-use-it-in-flutter-5blm</guid>
      <description>&lt;p&gt;This is what we have from &lt;a href="https://developer.apple.com/documentation/uikit/view_controllers/preserving_your_app_s_ui_across_launches?language=objc" rel="noopener noreferrer"&gt;Apple's documentation&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Preserving your app’s user interface helps maintain the illusion that your app is always running. Interruptions can occur frequently on iOS devices, and a prolonged interruption might cause the system to terminate your app to free up resources. However, users do not know that your app has been terminated and will not expect the state of your app to change. Instead, they expect your app to be in the same state as when they left it. State preservation and restoration ensures that your app returns to its previous state when it launches again.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Even though this comes from Apple, the same applies for Android apps as well. You can read the related Android documentation &lt;a href="https://developer.android.com/topic/libraries/architecture/saving-states" rel="noopener noreferrer"&gt;here&lt;/a&gt;. Before we procceed, note that this is all about the user experience and as developers, it is our responsability to implement and provide a good UX to our users. &lt;/p&gt;

&lt;p&gt;Ok, now that we have some knowleadge about what is SR and why it is important, let's se how it works in Flutter.&lt;/p&gt;

&lt;h2&gt;
  
  
  What about Flutter?
&lt;/h2&gt;

&lt;p&gt;Back in the days, this was a difficult task because we didn't have official support from the framework, basically we had to implement a cache strategy ourself, and this was not an easy task. See &lt;a href="https://github.com/flutter/flutter/issues/6827" rel="noopener noreferrer"&gt;issue #6827&lt;/a&gt; on GitHub.&lt;/p&gt;

&lt;p&gt;In Flutter &lt;code&gt;1.22&lt;/code&gt;, we now have Framework support for state restoration out of the box and this comes to save us a lot of time.&lt;/p&gt;

&lt;p&gt;Flutter give us an synchronous API for us to provide the data that represents the state of our UI to be saved every time it changes so that any time our app is destroyed, the engine already has the latest information of or UI to be saved into the OS and restored if the user comes back to our app.&lt;/p&gt;

&lt;h3&gt;
  
  
  New concepts, same finality
&lt;/h3&gt;

&lt;p&gt;If you come from Android (like me) or iOS, you will notice that the concepts are the same, we just have different ways of doing it.&lt;/p&gt;

&lt;p&gt;Flutter hava the &lt;code&gt;RestorationManager&lt;/code&gt;, which is the class that is responsible of handling all the state restoration work, usually we don't need to use it directly.  &lt;code&gt;RestorationBucket&lt;/code&gt; which is used to hold the piece of the restoration data that our app need to restore its state later. &lt;code&gt;RestorationScope&lt;/code&gt;, which is used to provide a scoped &lt;code&gt;RestorationBucket&lt;/code&gt; to its descendants, if the &lt;code&gt;restorationId&lt;/code&gt; parameter is null then, the restoration capability is disabled for its descedants. &lt;code&gt;RestorationMixin&lt;/code&gt; this is used by our widget's state, he is the one we will usually use, it provides a straightfoward API to save and restore our state. And finally we have restorable properties (one for each Dart's data type), which are used to represent the data to be stored in the buckets.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to use it?
&lt;/h2&gt;

&lt;p&gt;Flutter app widgets (&lt;code&gt;MaterialApp&lt;/code&gt;, &lt;code&gt;CupertinoApp&lt;/code&gt; and &lt;code&gt;WidgetsApp&lt;/code&gt;) has a &lt;code&gt;RootRestorationScope&lt;/code&gt; built-in by default so we don't need to provide one, instead we just need to provide an id that will be used by the inner root scope. Notice that without providing the restoration scope id, the state restoration feature will be turned off so make sure you don't miss this step.&lt;/p&gt;

&lt;p&gt;One of the advantages of providing the restoration scope id into our app widget is that it also enables the Navigator built by the &lt;code&gt;WidgetsApp&lt;/code&gt; to restore its state (i.e. to restore the history stack of active Routes). See the documentation on &lt;code&gt;Navigator&lt;/code&gt; for more details around state restoration of Routes.&lt;/p&gt;

&lt;p&gt;Let's see how we can use state restoration to save (and restore) the index of the &lt;code&gt;BottomNavigationBar&lt;/code&gt;. Here is what we need to do:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Provide a &lt;code&gt;restorationScopeId&lt;/code&gt; to our &lt;code&gt;MaterialApp&lt;/code&gt; (&lt;code&gt;CupertinoApp&lt;/code&gt; and &lt;code&gt;WidgetsApp&lt;/code&gt; also have this parameter);&lt;/li&gt;
&lt;li&gt;Our home page state should e mixed-in with &lt;code&gt;RestorationMixin&lt;/code&gt; (and implement its members);&lt;/li&gt;
&lt;li&gt;Create our restorable properties and use it instead of the common Dart's data type.&lt;/li&gt;
&lt;li&gt;Resgister our restorable properties for restoration;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;And that is it, Flutter will take care of the rest.&lt;/p&gt;

&lt;h2&gt;
  
  
  Example
&lt;/h2&gt;

&lt;p&gt;The code bellow will save the index of the bottom navigation bar if the app is killed.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="s"&gt;'package:flutter/material.dart'&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;runApp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;MyApp&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyApp&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="n"&gt;StatelessWidget&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nd"&gt;@override&lt;/span&gt;
  &lt;span class="n"&gt;Widget&lt;/span&gt; &lt;span class="n"&gt;build&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BuildContext&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;MaterialApp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="c1"&gt;// Give your RootRestorationScope an id, defaults to null.&lt;/span&gt;
      &lt;span class="nl"&gt;restorationScopeId:&lt;/span&gt; &lt;span class="s"&gt;'root'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
      &lt;span class="nl"&gt;home:&lt;/span&gt; &lt;span class="n"&gt;HomePage&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;HomePage&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="n"&gt;StatefulWidget&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nd"&gt;@override&lt;/span&gt;
  &lt;span class="n"&gt;_HomePageState&lt;/span&gt; &lt;span class="n"&gt;createState&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;_HomePageState&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Our state should be mixed-in with RestorationMixin&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;_HomePageState&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="n"&gt;State&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;HomePage&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;RestorationMixin&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="c1"&gt;// For each state, we need to use a restorable property&lt;/span&gt;
  &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;RestorableInt&lt;/span&gt; &lt;span class="n"&gt;_index&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;RestorableInt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nd"&gt;@override&lt;/span&gt;
  &lt;span class="n"&gt;Widget&lt;/span&gt; &lt;span class="n"&gt;build&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BuildContext&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;Scaffold&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="nl"&gt;body:&lt;/span&gt; &lt;span class="n"&gt;Center&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;child:&lt;/span&gt; &lt;span class="n"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'Index is &lt;/span&gt;&lt;span class="si"&gt;${_index.value}&lt;/span&gt;&lt;span class="s"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
      &lt;span class="nl"&gt;bottomNavigationBar:&lt;/span&gt; &lt;span class="n"&gt;BottomNavigationBar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nl"&gt;currentIndex:&lt;/span&gt; &lt;span class="n"&gt;_index&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nl"&gt;onTap:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;setState&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;_index&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="nl"&gt;items:&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;BottomNavigationBarItem&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;[&lt;/span&gt;
          &lt;span class="n"&gt;BottomNavigationBarItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
              &lt;span class="nl"&gt;icon:&lt;/span&gt; &lt;span class="n"&gt;Icon&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Icons&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;home&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
              &lt;span class="nl"&gt;label:&lt;/span&gt; &lt;span class="s"&gt;'Home'&lt;/span&gt;
          &lt;span class="p"&gt;),&lt;/span&gt;
          &lt;span class="n"&gt;BottomNavigationBarItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
              &lt;span class="nl"&gt;icon:&lt;/span&gt; &lt;span class="n"&gt;Icon&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Icons&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;notifications&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
              &lt;span class="nl"&gt;label:&lt;/span&gt; &lt;span class="s"&gt;'Notifications'&lt;/span&gt;
          &lt;span class="p"&gt;),&lt;/span&gt;
          &lt;span class="n"&gt;BottomNavigationBarItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
              &lt;span class="nl"&gt;icon:&lt;/span&gt; &lt;span class="n"&gt;Icon&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Icons&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;settings&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
              &lt;span class="nl"&gt;label:&lt;/span&gt; &lt;span class="s"&gt;'Settings'&lt;/span&gt;
          &lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="p"&gt;],&lt;/span&gt;
      &lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nd"&gt;@override&lt;/span&gt;
  &lt;span class="c1"&gt;// The restoration bucket id for this page,&lt;/span&gt;
  &lt;span class="c1"&gt;// let's give it the name of our page!&lt;/span&gt;
  &lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="kd"&gt;get&lt;/span&gt; &lt;span class="n"&gt;restorationId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="s"&gt;'home_page'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nd"&gt;@override&lt;/span&gt;
  &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="n"&gt;restoreState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;RestorationBucket&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="n"&gt;oldBucket&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;initialRestore&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Register our property to be saved every time it changes,&lt;/span&gt;
    &lt;span class="c1"&gt;// and to be restored every time our app is killed by the OS!&lt;/span&gt;
    &lt;span class="n"&gt;registerForRestoration&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_index&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'nav_bar_index'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  How to test?
&lt;/h3&gt;

&lt;p&gt;If you want to test this code (or your code during development), you will need to enable the "Don't keep activities" options in your device's Developer Options. &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Open the Developer options settings, and enable the option &lt;code&gt;Don't keep activities&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F1o7w89210qxdwtuvbw31.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F1o7w89210qxdwtuvbw31.jpeg" alt="Alt Text" width="383" height="680"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This will simulate the lack of memory and the device will kill all activities as soon as you leave it.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Run the code above app and tap the &lt;code&gt;Settings&lt;/code&gt; item;&lt;/li&gt;
&lt;li&gt;Go to the launcher by pressing the device's home button.
Press the overview button and return to the app.&lt;/li&gt;
&lt;li&gt;notice that the &lt;code&gt;Settings&lt;/code&gt; item is still selected.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fqnh23kra7o5mkgpkr4j4.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fqnh23kra7o5mkgpkr4j4.gif" alt="With State Restoration" width="420" height="886"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; You can try the same app without state restoration (find the code &lt;a href="https://gist.github.com/pedromassango/014501d092a15899b2bc27c28577334f" rel="noopener noreferrer"&gt;here&lt;/a&gt;), where if you run it and repeat the same steps you will notice that the index is always back to &lt;code&gt;Home&lt;/code&gt;once you launch the app again. Make sure you stop and run the code code again because state restoration code is not removed with hot-reload/restart as it is tied to the host OS!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F84a3tjj973b6guxixgzg.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F84a3tjj973b6guxixgzg.gif" alt="Without State Restoration" width="420" height="886"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That is it for today. There is still a lot of things to talk about state restoration and I will split into more than one article so make sure you follow me (here or on Twitter) to not miss the next one.&lt;/p&gt;

</description>
      <category>flutter</category>
      <category>dart</category>
      <category>android</category>
      <category>ios</category>
    </item>
    <item>
      <title>Flutter tip (#4): run a Flutter app to a specific route</title>
      <dc:creator>Pedro Massango</dc:creator>
      <pubDate>Sat, 05 Sep 2020 10:17:33 +0000</pubDate>
      <link>https://dev.to/pedromassango/flutter-tip-2-run-a-flutter-app-to-a-specific-route-17o</link>
      <guid>https://dev.to/pedromassango/flutter-tip-2-run-a-flutter-app-to-a-specific-route-17o</guid>
      <description>&lt;p&gt;Few days ago I found an hidden gem in the main Flutter repository and shared it on my &lt;a href="https://twitter.com/pedromassangom/status/1298634719966494725" rel="noopener noreferrer"&gt;Twitter account&lt;/a&gt; and today I tought its better to share on my blogpost.&lt;/p&gt;

&lt;p&gt;Have you ever wanted to run your Flutter app straight to a specific named route? yes it is possible.&lt;/p&gt;

&lt;p&gt;This is helpful when you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Want to test a specific page in your app and you don't want to run the whole app and navigate to that page by yourself.&lt;/li&gt;
&lt;li&gt;Want to test &lt;a href="http://sellsbrothers.com/understanding-flutter-deep-links-on-the-web" rel="noopener noreferrer"&gt;deep link&lt;/a&gt; in your Flutter app.&lt;/li&gt;
&lt;li&gt;(other) you may need it for many other use-cases :)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Show me the code
&lt;/h2&gt;

&lt;p&gt;All you need to do is to run the flutter command with the &lt;code&gt;--route&lt;/code&gt; parameter:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;pedromassago$ flutter run --route /routeName&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;--route&lt;/code&gt; parameter expect a string that is the route name that will be used to start your application with. In the case above the app will start with the &lt;code&gt;/routeName&lt;/code&gt; page in your screen.&lt;/p&gt;

&lt;h2&gt;
  
  
  Notes
&lt;/h2&gt;

&lt;p&gt;This feature is only available for Android devices at the time this post was written. There is a open issue to bring support for other platform like iOS at &lt;a href="https://github.com/flutter/flutter/issues/4703" rel="noopener noreferrer"&gt;flutter/flutter/issues/4703&lt;/a&gt;. If you wan this feature on iOS you can thumbs up the issue to get it fixed sooner.&lt;/p&gt;

&lt;p&gt;Thanks for you time! 😉&lt;/p&gt;

</description>
      <category>dart</category>
      <category>flutter</category>
    </item>
  </channel>
</rss>
