<?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: Andrea Bizzotto</title>
    <description>The latest articles on DEV Community by Andrea Bizzotto (@biz84).</description>
    <link>https://dev.to/biz84</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%2F143529%2Fb8cbc66e-ef54-4b2f-ad2f-57b83b449dab.png</url>
      <title>DEV Community: Andrea Bizzotto</title>
      <link>https://dev.to/biz84</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/biz84"/>
    <language>en</language>
    <item>
      <title>My 2020 as a Content Creator: Udemy, Teachable, and YouTube Revenue and Income Report</title>
      <dc:creator>Andrea Bizzotto</dc:creator>
      <pubDate>Fri, 01 Jan 2021 15:22:24 +0000</pubDate>
      <link>https://dev.to/biz84/my-2020-as-a-content-creator-udemy-teachable-and-youtube-revenue-and-income-report-1kj8</link>
      <guid>https://dev.to/biz84/my-2020-as-a-content-creator-udemy-teachable-and-youtube-revenue-and-income-report-1kj8</guid>
      <description>&lt;p&gt;2020 marked my third year as a &lt;strong&gt;content creator&lt;/strong&gt; making Flutter tutorials and courses on Udemy, YouTube, and my own website.&lt;/p&gt;

&lt;p&gt;In this article, I share a full retrospective about my sales numbers, along with a lot of details about my journey and milestones.&lt;br&gt;
I'll also explain how I used Udemy, YouTube, Teachable, Twitter, my website, and many other channels to &lt;strong&gt;grow my audience and business&lt;/strong&gt;.&lt;/p&gt;




&lt;p&gt;In reality, 2020 has been a tragic year for many people who have lost loved ones. I can only be grateful that everything has gone as well as it could have in my own life. Being able to focus on my work from the comfort of my home has kept me sane and safe, and I'm aware that many others don't have this privilege.&lt;/p&gt;

&lt;p&gt;I'm about to share my successes and insights from this year, because I feel they are valuable and worth sharing. If you had a tough year and didn't accomplish as much, I want you to know it's ok. You can read this retrospective for what it is, but don't compare yourself to me.&lt;/p&gt;




&lt;p&gt;So let me give you a realistic picture of what it's like to run a content creation business, starting from my motivation:&lt;/p&gt;

&lt;h2&gt;
  
  
  Why did I become a content creator?
&lt;/h2&gt;

&lt;p&gt;Before becoming a content creator I was contract iOS developer for many years, working on many diverse and interesting projects. &lt;/p&gt;

&lt;p&gt;I had the flexibility to take time off and work on side projects between contracts, due to strong demand and competitive market rates for iOS developers in London.&lt;/p&gt;

&lt;p&gt;So why did I decide to leave that behind and make Flutter tutorials and courses instead?&lt;/p&gt;

&lt;p&gt;Ultimately, my decision came down to this:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I want to have &lt;strong&gt;full creative control&lt;/strong&gt; over my work, be my own boss, on my own schedule.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I'm very passionate about coding and helping people learn to code, no matter where they are in the world.&lt;/p&gt;

&lt;p&gt;Content creation gives me an avenue to do that and brings a lot of exciting challenges. I started creating Flutter video tutorials &lt;a href="https://nnbd.me/yt" rel="noopener noreferrer"&gt;on YouTube&lt;/a&gt; and courses on Udemy. In 2020 I've launched &lt;a href="https://dev.to/"&gt;CodeWithAndrea.com&lt;/a&gt; as a platform to share all my content in one place.&lt;/p&gt;

&lt;p&gt;In addition to coding, my daily work includes writing articles, making videos, marketing, and growing an audience across multiple platforms. &lt;/p&gt;

&lt;p&gt;All the things I do boil down to this: &lt;strong&gt;how can I productize my knowledge&lt;/strong&gt; and make a living from it?&lt;/p&gt;

&lt;p&gt;This is not easy and is not for everyone. Daniell Vassallo said it best in this &lt;a href="https://twitter.com/dvassallo/status/1340358943457988608" rel="noopener noreferrer"&gt;recent tweet&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The problem with scalable work (where income and effort are decoupled) is that your odds of success are very low.&lt;br&gt;
The stars need to align to make it work, and if they don't you'll make nothing. This is not the case with non-scalable work.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;With this in mind, I can now share my goals for this year and show you how I've done.&lt;/p&gt;

&lt;h2&gt;
  
  
  2020 Goals
&lt;/h2&gt;

&lt;p&gt;In closing &lt;a href="https://dev.to/videos/2020-01-13-2019-retrospective-udemy-youtube/"&gt;last year's retrospective&lt;/a&gt;, I set myself some goals:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Launch (at least) one more course&lt;/li&gt;
&lt;li&gt;$5,000 monthly average revenue (MAR) (from $2,400)&lt;/li&gt;
&lt;li&gt;Reach 30K subscribers on YouTube (from 10.5K)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Note: I don't get monthly recurring revenue (MRR) by selling Udemy courses, so I'll use the monthly average revenue (MAR) over the last 4 months as a metric instead.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This year I launched two new courses (more on that later), so I've accomplished my first goal. ✅&lt;/p&gt;

&lt;p&gt;Next, I'll show you my full income report. After that, I'll share a lot of insights about my content creation strategy and journey.&lt;/p&gt;

&lt;h2&gt;
  
  
  2020 Income Report
&lt;/h2&gt;

&lt;p&gt;This year I've been earning income across three platforms: Udemy, Teachable, and YouTube (via AdSense).&lt;/p&gt;

&lt;p&gt;Here's a monthly breakdown across all platforms:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcodewithandrea.com%2Fvideos%2Fcontent-creator-udemy-teachable-youtube-2020-income-report%2Fimages%2Ftotal-2020-revenue.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcodewithandrea.com%2Fvideos%2Fcontent-creator-udemy-teachable-youtube-2020-income-report%2Fimages%2Ftotal-2020-revenue.png" alt="2020 Income breakdown: Udemy vs Teachable vs YouTube"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;center&gt;2020 income report across Udemy, Teachable, YouTube (AdSense)&lt;/center&gt;

&lt;p&gt;My total earnings have reached just under $43,000, at roughly $3580 per month.&lt;/p&gt;

&lt;p&gt;Of these, Udemy took the cake, at over %90 of my income. So let's look at that in more detail.&lt;/p&gt;

&lt;h2&gt;
  
  
  2020 Udemy Income
&lt;/h2&gt;

&lt;p&gt;My Udemy lifetime earnings look like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcodewithandrea.com%2Fvideos%2Fcontent-creator-udemy-teachable-youtube-2020-income-report%2Fimages%2Fudemy-lifetime-revenue.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcodewithandrea.com%2Fvideos%2Fcontent-creator-udemy-teachable-youtube-2020-income-report%2Fimages%2Fudemy-lifetime-revenue.png" alt="Udemy lifetime earnings since March 2019"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;center&gt;Udemy lifetime earnings since March 2019&lt;/center&gt;

&lt;p&gt;I'm happy to have passed the $50K milestone. Though monthly average revenue (MAR) is of course the most interesting metric.&lt;/p&gt;

&lt;p&gt;Over the last four months (September to December) my MAR reached $4,250, which is short of my $5K goal. ❌&lt;/p&gt;

&lt;p&gt;Note: sales numbers are very &lt;strong&gt;seasonal&lt;/strong&gt;, as Udemy runs many promotions in different countries at different times of the year. While the chart above shows an increasing trend, I expect sales to dip in Q1 2021.&lt;/p&gt;

&lt;p&gt;In September alone, I managed to drive nearly $3,700 in sales from my own promotions, thanks to the launch of my new &lt;a href="https://nnbd.me/dart" rel="noopener noreferrer"&gt;Dart course&lt;/a&gt;. And I was quite happy about it:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcodewithandrea.com%2Fvideos%2Fcontent-creator-udemy-teachable-youtube-2020-income-report%2Fimages%2Fdart-course-launch.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcodewithandrea.com%2Fvideos%2Fcontent-creator-udemy-teachable-youtube-2020-income-report%2Fimages%2Fdart-course-launch.jpeg" alt="Celebrating my Dart Course launch"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;November has been my best month so far with $5,000 in revenue, due to Udemy's Black Friday promotions.&lt;/p&gt;

&lt;p&gt;This year my Udemy income was distributed like this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;45%&lt;/strong&gt; from my own promotions&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;55%&lt;/strong&gt; from Udemy organic, affiliates, and the ads program.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In other words, while Udemy traffic contributes to ~55% of my sales, I still have to &lt;strong&gt;consistently promote&lt;/strong&gt; my courses to break through the $4,000 MAR mark. For comparison, top instructors earn a lot more in volume sales from Udemy organic traffic.&lt;/p&gt;

&lt;p&gt;$4,000 MAR makes me financially comfortable (some would say &lt;a href="http://www.paulgraham.com/ramenprofitable.html" rel="noopener noreferrer"&gt;ramen profitable&lt;/a&gt;) and I can fully focus on my business without doing extra consulting work to pay the bills. 🙂&lt;/p&gt;

&lt;p&gt;Here's how each of my three Udemy courses performed:&lt;/p&gt;

&lt;h3&gt;
  
  
  Flutter &amp;amp; Firebase Course
&lt;/h3&gt;

&lt;p&gt;This is my oldest and longest course, with 21 hours of content. It received a big spike in sales in April / May, as more people were learning online during the first COVID lockdown. But it has been on a down-trend since then:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcodewithandrea.com%2Fvideos%2Fcontent-creator-udemy-teachable-youtube-2020-income-report%2Fimages%2Fflutter-firebase-course-revenue.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcodewithandrea.com%2Fvideos%2Fcontent-creator-udemy-teachable-youtube-2020-income-report%2Fimages%2Fflutter-firebase-course-revenue.png" alt="Flutter &amp;amp; Firebase course revenue in 2020"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;center&gt;2020 monthly income from my Flutter &amp;amp; Firebase course on Udemy&lt;/center&gt;

&lt;p&gt;In August, the &lt;a href="https://firebase.flutter.dev/" rel="noopener noreferrer"&gt;FlutterFire&lt;/a&gt; plugins received a major update that introduced many breaking changes, and course ratings dropped from 4.7 to 4.6 as a result. I managed to update the course in November, but the ratings haven't climbed back up yet.&lt;/p&gt;

&lt;h3&gt;
  
  
  Flutter REST API Course
&lt;/h3&gt;

&lt;p&gt;I launched this course in March on Teachable, and in late April on Udemy:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcodewithandrea.com%2Fvideos%2Fcontent-creator-udemy-teachable-youtube-2020-income-report%2Fimages%2Fflutter-rest-api-course-revenue.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcodewithandrea.com%2Fvideos%2Fcontent-creator-udemy-teachable-youtube-2020-income-report%2Fimages%2Fflutter-rest-api-course-revenue.png" alt="Flutter REST API course revenue in 2020"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;center&gt;Monthly income from my Dart course on Udemy (launched April 2020)&lt;/center&gt;

&lt;p&gt;This course is much smaller (2.5 hours of content) and has not been getting a good volume of sales due to its lower ranking on the Udemy charts.&lt;/p&gt;

&lt;p&gt;In an attempt to improve this, I did something outlandish and made the course free for 3 days in October. I shared this on Twitter and Reddit, and gathered over 15,000 enrollments 🤯. This is very noticeable in the traffic &amp;amp; conversion report:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcodewithandrea.com%2Fvideos%2Fcontent-creator-udemy-teachable-youtube-2020-income-report%2Fimages%2Fflutter-rest-api-course-visitors.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcodewithandrea.com%2Fvideos%2Fcontent-creator-udemy-teachable-youtube-2020-income-report%2Fimages%2Fflutter-rest-api-course-visitors.png" alt="Spike in visitors during free 3 day promotion"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;center&gt;The result of making my course free for 3 days: a huge spike in landing page visitors.&lt;/center&gt;

&lt;p&gt;The result of this experiment?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the number of reviews doubled to over 200&lt;/li&gt;
&lt;li&gt;the average review score dropped from 4.7 to 4.5&lt;/li&gt;
&lt;li&gt;over the next two months, the course ranking went from #52 to #7 for "flutter"&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The extra reviews helped with sales, most likely due to increased visibility during Black Friday. But this was a gamble. All those "free" students never bought my other paid courses, and I will not try this again. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Lesson learned: Never give away your paid content for free.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This is a hack that &lt;em&gt;can&lt;/em&gt; help boost rankings, at the expense of jeopardizing reviews and attracting the wrong students. And I wouldn't risk this on my most valuable courses.&lt;/p&gt;

&lt;h3&gt;
  
  
  Dart Course
&lt;/h3&gt;

&lt;p&gt;This is my newest course. It took 4 months to produce and ended up being a &lt;a href="https://nnbd.me/dart" rel="noopener noreferrer"&gt;comprehensive Dart course for beginners&lt;/a&gt; with 10 hours of content:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcodewithandrea.com%2Fvideos%2Fcontent-creator-udemy-teachable-youtube-2020-income-report%2Fimages%2Fdart-course-revenue.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcodewithandrea.com%2Fvideos%2Fcontent-creator-udemy-teachable-youtube-2020-income-report%2Fimages%2Fdart-course-revenue.png" alt="Dart course revenue in 2020"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;center&gt;Monthly income from my Dart course on Udemy (launched September 2020)&lt;/center&gt;

&lt;p&gt;I launched it and promoted it heavily in September, and it has been performing fairly well since.&lt;/p&gt;

&lt;p&gt;This course is now rated 4.8 stars and I often see people recommending it on Twitter and Reddit. It has even &lt;a href="https://twitter.com/mkobuolys/status/1331904010865950721" rel="noopener noreferrer"&gt;been gifted&lt;/a&gt; at some Flutter conferences. 🤗&lt;/p&gt;




&lt;p&gt;Udemy is a crowded marketplace. So how have I been able to generate these sales numbers?&lt;/p&gt;

&lt;h2&gt;
  
  
  Udemy is a very crowded platform
&lt;/h2&gt;

&lt;p&gt;Udemy is like a smaller version of Google, for paid online courses.&lt;/p&gt;

&lt;p&gt;Courses in the top 10 for a given category have a better chance of getting good search traffic, as well as being &lt;strong&gt;featured&lt;/strong&gt; and &lt;strong&gt;advertised&lt;/strong&gt; by Udemy. While many factors influence the ranking of courses on Udemy, the top two appear to be the &lt;strong&gt;number of reviews&lt;/strong&gt; and the &lt;strong&gt;average review score&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;So if you're planning to launch a course on Udemy, you need to carefully evaluate how much competition there is for the &lt;strong&gt;primary course topic&lt;/strong&gt;, and how likely you are to break into top #10 for the &lt;strong&gt;number of reviews&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;According to the &lt;a href="https://www.udemy.com/instructor/marketplace-insights/?q=Google%20Flutter&amp;amp;lang=en" rel="noopener noreferrer"&gt;Udemy insights page for Flutter&lt;/a&gt;, the &lt;strong&gt;average monthly revenue&lt;/strong&gt; of the top 5 courses is &lt;strong&gt;$20,000&lt;/strong&gt;, while the &lt;strong&gt;median monthly revenue&lt;/strong&gt; is under &lt;strong&gt;$50&lt;/strong&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcodewithandrea.com%2Fvideos%2Fcontent-creator-udemy-teachable-youtube-2020-income-report%2Fimages%2Fudemy-insights-google-flutter.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcodewithandrea.com%2Fvideos%2Fcontent-creator-udemy-teachable-youtube-2020-income-report%2Fimages%2Fudemy-insights-google-flutter.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;center&gt;Udemy insights page for the "Google Flutter" topic&lt;/center&gt;

&lt;p&gt;In other words, the &lt;strong&gt;winner takes all&lt;/strong&gt;. As there are now nearly &lt;strong&gt;600&lt;/strong&gt; Flutter courses (&lt;em&gt;a 10x increase compared to 15 months ago&lt;/em&gt;), my future courses will have a &lt;strong&gt;decreasing chance&lt;/strong&gt; of being discovered.&lt;/p&gt;

&lt;p&gt;Still, Udemy offers a &lt;strong&gt;promotional email feature&lt;/strong&gt; that instructors can use to market new courses to their existing students. Here is how my promotions have performed so far:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcodewithandrea.com%2Fvideos%2Fcontent-creator-udemy-teachable-youtube-2020-income-report%2Fimages%2Fudemy-promotional-announcements-ctr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcodewithandrea.com%2Fvideos%2Fcontent-creator-udemy-teachable-youtube-2020-income-report%2Fimages%2Fudemy-promotional-announcements-ctr.png" alt="Udemy promotional announcements"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;center&gt;Open Rate and CTR for my promotional emails on Udemy&lt;/center&gt;

&lt;p&gt;I'm no CTR expert but click-through rates of over 10% sound very good to me. For comparison, CTR in my regular email newsletters has been around 4% this year.&lt;/p&gt;

&lt;p&gt;With a combination of promotional emails and announcements on YouTube and Twitter, I got enough students and reviews to make all my three courses rank in the top 10 for Flutter / Dart.&lt;/p&gt;

&lt;p&gt;But with over 600 Flutter courses on Udemy, I'm not sure that my future courses will do well enough to break even, &lt;em&gt;no matter how good they are&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Because Udemy is all about &lt;strong&gt;volume&lt;/strong&gt;, most courses cater to &lt;strong&gt;beginners&lt;/strong&gt;. Maybe I should publish my future courses somewhere else, for a higher price. After all, there are many ways of making $50,000 with a course:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;5000&lt;/strong&gt; sales for &lt;strong&gt;$10&lt;/strong&gt; each&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;1000&lt;/strong&gt; sales for &lt;strong&gt;$50&lt;/strong&gt; each&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;500&lt;/strong&gt; sales for &lt;strong&gt;$100&lt;/strong&gt; each&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This brings me to Teachable.&lt;/p&gt;

&lt;h2&gt;
  
  
  Teachable as a course platform
&lt;/h2&gt;

&lt;p&gt;After seeing other creators have success on Teachable, I decided to use it to host my &lt;a href="https://courses.codewithandrea.com" rel="noopener noreferrer"&gt;Flutter REST API course&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This course shows how to use REST APIs to build a Coronavirus app in Flutter. I launched this course in March, right when most of Europe and the US were experiencing the first wave of COVID.&lt;/p&gt;

&lt;p&gt;To drive students to this course, I shared a &lt;a href="https://www.youtube.com/playlist?list=PLNnAcB93JKV_BVgWZn7I_ewWKP2hpAqLr" rel="noopener noreferrer"&gt;couple of chapters&lt;/a&gt; for free on YouTube, and these were some of my most-watched videos this year.&lt;/p&gt;

&lt;p&gt;I made $1,700 in the first month, but sales dropped sharply after that:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcodewithandrea.com%2Fvideos%2Fcontent-creator-udemy-teachable-youtube-2020-income-report%2Fimages%2Fteachable-2020-earnings.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcodewithandrea.com%2Fvideos%2Fcontent-creator-udemy-teachable-youtube-2020-income-report%2Fimages%2Fteachable-2020-earnings.png" alt="My sales on Teachable in 2020"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;center&gt;2020 income from sales on Teachable&lt;/center&gt;

&lt;p&gt;This highlights one important thing:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Udemy is a &lt;strong&gt;marketplace&lt;/strong&gt; with a &lt;strong&gt;lot of traffic&lt;/strong&gt; and built-in &lt;strong&gt;search&lt;/strong&gt; and &lt;strong&gt;discovery&lt;/strong&gt; features to help students find your courses.&lt;/li&gt;
&lt;li&gt;Teachable &lt;strong&gt;does not market&lt;/strong&gt; your courses for you. Instead, you have to drive all the traffic yourself.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Unlike Udemy, Teachable gives you full control over the course price, and after students enroll you have their emails. But when you are starting out and your audience is small, it's hard to get enough people to buy your course.&lt;/p&gt;

&lt;p&gt;To be fair, Teachable already has a large pool of students and offers various ways (e.g. webinars) for instructors to promote their courses. I have not tried these marketing channels yet, and I'm keen to do so next year.&lt;/p&gt;




&lt;p&gt;But as I continue growing my audience and newsletter (more on this below), it may make sense to sell higher-priced, premium courses exclusively on Teachable or other platforms. Time will tell.&lt;/p&gt;

&lt;h2&gt;
  
  
  My year on YouTube
&lt;/h2&gt;

&lt;p&gt;YouTube is the second biggest search engine in the world and I really like it as a platform.&lt;/p&gt;

&lt;p&gt;My goal was to increase my subscribers from 10K to 30K this year. But I didn't reach this goal and stopped at 23K instead. ❌&lt;/p&gt;

&lt;p&gt;This is due to two reasons:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;My primary focus has been on creating paid courses&lt;/li&gt;
&lt;li&gt;Many of my videos didn't do great (less than 1000 views on week 1) rather than "everyone likes this" (over 10,000 views on week 1)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here's a chart of my channel watch time this year:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcodewithandrea.com%2Fvideos%2Fcontent-creator-udemy-teachable-youtube-2020-income-report%2Fimages%2Fyoutube-2020-watch-time.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcodewithandrea.com%2Fvideos%2Fcontent-creator-udemy-teachable-youtube-2020-income-report%2Fimages%2Fyoutube-2020-watch-time.png" alt="YouTube watch time in 2020"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;center&gt;Watch time (hours) on my YouTube channel in 2020&lt;/center&gt;

&lt;p&gt;This is mostly flat - even decreasing in the second half of the year.&lt;/p&gt;

&lt;p&gt;That's because from July until October I focused 100% on creating my Dart course, and haven't been able to publish a lot of interesting content.&lt;/p&gt;

&lt;p&gt;In the first part of the year, I tried to publish YouTube videos consistently, but I didn't have a clear strategy and wasn't getting results.&lt;/p&gt;

&lt;p&gt;For comparison purposes, some of the top programming YouTube channels have been growing 5x to 10x faster than mine. So the bar is getting higher on YouTube, and I need to step up my game in 2021.&lt;/p&gt;

&lt;h2&gt;
  
  
  As a content creator, what are the right metrics?
&lt;/h2&gt;

&lt;p&gt;To be fair, I see YouTube as a valuable channel to increase my audience, but it is only one piece of the puzzle.&lt;/p&gt;

&lt;p&gt;As I have written &lt;a href="https://dev.to/articles/2020-11-07-content-creation-blueprint/"&gt;in my content creation blueprint&lt;/a&gt;, I'm active on many channels.&lt;/p&gt;

&lt;p&gt;If I want to grow my business sustainably and continue to create valuable content (both free and paid), I need to focus on the right metrics:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;more Twitter followers? nice&lt;/li&gt;
&lt;li&gt;more YouTube subs? cool&lt;/li&gt;
&lt;li&gt;more unique visitors to my site? great&lt;/li&gt;
&lt;li&gt;more email subscribers? awesome&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But what matters the most is &lt;strong&gt;how many students enroll in my paid courses&lt;/strong&gt; every month. I can only continue making free Flutter tutorials for everyone &lt;strong&gt;if my paid courses pay the bills&lt;/strong&gt;. &lt;em&gt;By the way, &lt;a href="https://dev.to/courses/"&gt;you can buy them here&lt;/a&gt; to support my work.&lt;/em&gt; 🙏&lt;/p&gt;

&lt;p&gt;Each platform is unique in its own way. Twitter alone has performed very well for me this year.&lt;/p&gt;

&lt;p&gt;But I feel that going forward my website and email list will be a major focus. Speaking of which...&lt;/p&gt;

&lt;h2&gt;
  
  
  CodeWithAndrea.com
&lt;/h2&gt;

&lt;p&gt;Launching &lt;a href="https://dev.to/"&gt;this website&lt;/a&gt; in 2020 has been a great move.&lt;/p&gt;

&lt;p&gt;My website holds all my content in one place. It's a platform that I &lt;strong&gt;own&lt;/strong&gt; and I can use it as a funnel for my paid courses and newsletter.&lt;/p&gt;

&lt;p&gt;Here are my traffic stats from this year:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcodewithandrea.com%2Fvideos%2Fcontent-creator-udemy-teachable-youtube-2020-income-report%2Fimages%2Fwebsite-2020-stats.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcodewithandrea.com%2Fvideos%2Fcontent-creator-udemy-teachable-youtube-2020-income-report%2Fimages%2Fwebsite-2020-stats.png" alt="Monthly data for CodeWithAndrea.com"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;center&gt;Page-views and unique visitors trend on CodeWithAndrea.com&lt;/center&gt;

&lt;p&gt;After launching the site in January, I set up &lt;strong&gt;canonical URLs&lt;/strong&gt; for all pages in my previous Medium publication, and I reached 40,000 page views in May.&lt;/p&gt;

&lt;p&gt;Though I haven't published a lot of content between July-October, and my unique visitors have remained flat during this period.&lt;/p&gt;

&lt;p&gt;And just as I started finding time to focus on my site, I discovered...&lt;/p&gt;

&lt;h3&gt;
  
  
  The Blogging For Devs community
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://bloggingfordevs.com/pro/" rel="noopener noreferrer"&gt;Blogging For Devs Pro&lt;/a&gt; is a great community of developers who are growing their audience through blogging. Joining this community has been one of the &lt;strong&gt;best investments&lt;/strong&gt; I've done for my business.&lt;/p&gt;

&lt;p&gt;I've learned a ton of stuff about blogging, SEO, email &amp;amp; newsletters, and much more. Even better, I've been able to share my work and get feedback from other creators &lt;strong&gt;daily&lt;/strong&gt;. I think of this community as a form of &lt;strong&gt;shared mentorship&lt;/strong&gt;. &lt;a href="https://monicalent.com/" rel="noopener noreferrer"&gt;Monica Lent&lt;/a&gt; (the author) knows "a ridiculous amount about blogging" (in her own words), and has been consistently helping me and others take our blogs to the next level.&lt;/p&gt;




&lt;p&gt;Empowered by this discovery, I set off fixing the most outstanding SEO issues on my site and increased traffic by 25% in one month. I updated some of my old articles using better keywords and boosted traffic even more.&lt;/p&gt;

&lt;p&gt;And I also launched a brand &lt;a href="https://dev.to/newsletter/"&gt;new newsletter&lt;/a&gt;, redesigned parts of my website, and started planning a sound content strategy for 2021.&lt;/p&gt;

&lt;h2&gt;
  
  
  My new newsletter
&lt;/h2&gt;

&lt;p&gt;My old newsletter was hardly getting any new subscribers for most of 2020. That's because I was just showing a boring sign-up banner on my website.&lt;/p&gt;

&lt;p&gt;Having seen what Monica had done with &lt;a href="https://bloggingfordevs.com/" rel="noopener noreferrer"&gt;her newsletter&lt;/a&gt;, I figured I could do much better.&lt;/p&gt;

&lt;p&gt;So I created a 15-day &lt;a href="https://dev.to/newsletter/"&gt;email course&lt;/a&gt; offering a &lt;strong&gt;curated&lt;/strong&gt; list of resources to help people learn Flutter at their own pace.&lt;/p&gt;

&lt;p&gt;I only launched this newsletter 10 days ago, but I can already report that I got nearly 400 new subscribers on launch day - that's 10% of the total subscribers in the previous &lt;strong&gt;three years&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcodewithandrea.com%2Fvideos%2Fcontent-creator-udemy-teachable-youtube-2020-income-report%2Fimages%2Fnewsletter-december-subscribers.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcodewithandrea.com%2Fvideos%2Fcontent-creator-udemy-teachable-youtube-2020-income-report%2Fimages%2Fnewsletter-december-subscribers.png" alt="Newsletter launch: net subscribers on first week"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;center&gt;New newsletter subscribers on launch week&lt;/center&gt;

&lt;p&gt;I can offer a lot of value with this newsletter. More importantly, I can talk &lt;strong&gt;directly&lt;/strong&gt; to my subscribers, figure out how to best help them, and better plan my strategy going forward.&lt;/p&gt;

&lt;h2&gt;
  
  
  Twitter and other platforms
&lt;/h2&gt;

&lt;p&gt;Udemy, Teachable, YouTube, and my website have kept me busy in 2020. But I've used other platforms too.&lt;/p&gt;

&lt;p&gt;This year I managed to reach 5000 Twitter followers, doubling the number from the previous year. Nearly all my Twitter followers are Flutter enthusiasts and I've been tweeting almost exclusively about Flutter. Having a &lt;strong&gt;targeted audience&lt;/strong&gt; makes Twitter a strategic platform for me.&lt;/p&gt;

&lt;p&gt;In July, I started a &lt;a href="https://twitter.com/search?q=from%3Abiz84%20easy%20win&amp;amp;src=typed_query&amp;amp;f=live" rel="noopener noreferrer"&gt;series of daily&lt;/a&gt; "Easy Wins" about the Dart language. These included bite-sized tips and tricks and have been very popular. I didn't quite make it to 100 tips and ran out of ideas at #43 😅, but I gained a lot of followers along the way. &lt;/p&gt;

&lt;p&gt;This contributed to the successful launch of my Dart course in September, and for the first time, I exceeded $1,000 in sales on launch day.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Bottom line&lt;/strong&gt;: it's worthwhile to build a loyal, &lt;strong&gt;qualified&lt;/strong&gt; audience on Twitter.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;People often reach out to me with questions, or even looking to hire me. While I'm focusing primarily on my business, it's good to know that I can easily find work if needed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Breakdown of my activities in 2020
&lt;/h2&gt;

&lt;p&gt;Content creation is not about passive income. &lt;/p&gt;

&lt;p&gt;I've been working on my business for &lt;strong&gt;almost 3 years&lt;/strong&gt; and my results have not come overnight.&lt;/p&gt;

&lt;p&gt;This year alone I spent a total of &lt;strong&gt;1198 hours&lt;/strong&gt; growing my business, for an average of 23 hours per week. That may not sound like much, but I've also done some contract work, taken up with some hobbies, and - most importantly - spent some time with my family. So this is the right balance for me.&lt;/p&gt;

&lt;p&gt;Here's a breakdown for activity type:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Dart Course: &lt;strong&gt;310h&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;YouTube Production: &lt;strong&gt;147h&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Blogging: &lt;strong&gt;135h&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Flutter Rest API Course: &lt;strong&gt;109h&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Website: &lt;strong&gt;89h&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Community engagement: &lt;strong&gt;86h&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Development: &lt;strong&gt;76h&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Flutter &amp;amp; Firebase Course: &lt;strong&gt;64h&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Newsletter: &lt;strong&gt;38h&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Planning: &lt;strong&gt;35h&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Other: &lt;strong&gt;107h&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcodewithandrea.com%2Fvideos%2Fcontent-creator-udemy-teachable-youtube-2020-income-report%2Fimages%2Ftime-breakdown-2020.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcodewithandrea.com%2Fvideos%2Fcontent-creator-udemy-teachable-youtube-2020-income-report%2Fimages%2Ftime-breakdown-2020.png" alt="2020 - time spent per activity type"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;center&gt;Percentage of time spent for all my activities in 2020&lt;/center&gt;

&lt;p&gt;Course production and updates have taken 42% of my time. Another 22% went into creating free content (articles and videos) for the Flutter community. And the rest was a mix of answering questions, building features for my website and newsletter, and writing open source Flutter apps and other test projects.&lt;/p&gt;

&lt;p&gt;From a purely financial point of view, what is my return on investment?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Total Revenue / Total Time Invested = &lt;strong&gt;$36 per hour&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is less than half of what I can earn as a contract developer and I hope to push this above $50 next year.&lt;/p&gt;

&lt;h2&gt;
  
  
  Ongoing Expenses
&lt;/h2&gt;

&lt;p&gt;All the numbers above don't tell the entire story, as some of my costs have gone up this year.&lt;/p&gt;

&lt;p&gt;Between ConvertKit, Ahrefs, Teachable, and other ongoing subscriptions, my expenses are now around $500 per month.&lt;/p&gt;

&lt;p&gt;While I should be able to reduce some of my costs next year, I'll also invest in better video production software &amp;amp; hardware.&lt;/p&gt;

&lt;p&gt;My ongoing expenses are less than 20% of my revenue. As long as my profits increase, I'm happy to invest in things that make me productive and help me produce better content.&lt;/p&gt;

&lt;p&gt;For example, this year I hired a designer to make some professional banners for my videos and courses, and I'm glad I did!&lt;/p&gt;

&lt;h2&gt;
  
  
  Content Creation - the drawbacks
&lt;/h2&gt;

&lt;p&gt;While launching more courses has boosted my revenue this year, not everything is as rosy as it seems.&lt;/p&gt;

&lt;h3&gt;
  
  
  Stuff changes all the time
&lt;/h3&gt;

&lt;p&gt;As languages and frameworks evolve at a rapid pace, courses and tutorials &lt;strong&gt;age quickly&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;APIs change often (I'm looking at you &lt;a href="https://firebase.flutter.dev/" rel="noopener noreferrer"&gt;FlutterFire&lt;/a&gt;), new packages are added all the time, and it takes a lot of work to keep content up to date.&lt;/p&gt;

&lt;p&gt;I have seen this happen with my &lt;a href="https://nnbd.me/ff" rel="noopener noreferrer"&gt;Flutter &amp;amp; Firebase course&lt;/a&gt;. While it's still a very valuable resource and I've managed to keep it updated, much has changed with Flutter state management and other topics. I've considered creating a brand new course to replace it. But that could take easily 6+ months of work and there's no guarantee that it would do well on Udemy.&lt;/p&gt;

&lt;h3&gt;
  
  
  Content Creation vs Building SaaS products vs Consulting
&lt;/h3&gt;

&lt;p&gt;Creating content about programming is a two-edged sword:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;on one hand, new stuff comes out all the time and there are endless opportunities to help people learn&lt;/li&gt;
&lt;li&gt;on the other hand, old content needs to be renewed often to remain relevant&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Keeping info-products (courses, books) updated takes time and this is a problem as a creator.&lt;/p&gt;

&lt;p&gt;Maybe I could get a better return on investment (ROI) building a SaaS product and this is something that I want to explore in 2021.&lt;/p&gt;

&lt;p&gt;To this day I still find it easier, more profitable, and &lt;strong&gt;reliable&lt;/strong&gt;, to earn a living doing consulting work than creating content. This is likely the case for most developers out there. &lt;em&gt;So don't jump on the content creation bandwagon just because you see others doing it on YouTube.&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Other content creation drawbacks
&lt;/h3&gt;

&lt;p&gt;Content creation has taken me away from coding more than I'd like to admit. &lt;/p&gt;

&lt;p&gt;My course creation process takes months, and is not as much fun as coding new stuff and learning things.&lt;/p&gt;

&lt;p&gt;Since launching my first course, I've made a point of answering all student questions. This is much appreciated and contributed to better reviews.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Trivia time&lt;/strong&gt;: did you know that Udemy no longer has a minimum $10 price for courses? When students from low-income countries purchase my courses through Udemy's affiliate program, I can make &lt;strong&gt;as low as $1 per sale&lt;/strong&gt;. While I still offer Q/A support to everyone, I'm doing it at a loss.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Some students ask good, thoughtful questions after researching their problem. Others just paste screenshots of common errors that they could have resolved very quickly by checking Google or StackOverflow. I don't feel those are the right kind of students for me.&lt;/p&gt;

&lt;p&gt;On a brighter note...&lt;/p&gt;

&lt;h2&gt;
  
  
  Helping People Learn
&lt;/h2&gt;

&lt;p&gt;So far I've shared a complete breakdown of all the $$$ I made. But you know what?&lt;/p&gt;

&lt;h3&gt;
  
  
  value &amp;gt; money
&lt;/h3&gt;

&lt;p&gt;In 2020 alone, thousands of students have watched 36,000 hours of tutorials from my YouTube channel.&lt;/p&gt;

&lt;p&gt;7500 students have watched nearly 50,000 hours of lessons from my Udemy courses:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcodewithandrea.com%2Fvideos%2Fcontent-creator-udemy-teachable-youtube-2020-income-report%2Fimages%2Fudemy-minutes-taught.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcodewithandrea.com%2Fvideos%2Fcontent-creator-udemy-teachable-youtube-2020-income-report%2Fimages%2Fudemy-minutes-taught.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;center&gt;Minutes taught each month on my Udemy courses&lt;/center&gt;

&lt;p&gt;Some of those students have gone on to create their own apps, even got jobs as Flutter developers.&lt;/p&gt;

&lt;p&gt;For me it's incredibly rewarding to help others grow and live a better life. I hope I can do so for even more people in the future.&lt;/p&gt;

&lt;p&gt;This leads me to my goals for 2021:&lt;/p&gt;

&lt;h2&gt;
  
  
  2021 Goals
&lt;/h2&gt;

&lt;p&gt;I could set some ambitious goal like reaching $10K per month, or have some explosive growth metrics. But that is unrealistic and would put a lot of pressure on myself.&lt;/p&gt;

&lt;p&gt;So I'm going to diversify my income a bit.&lt;/p&gt;

&lt;p&gt;In 2021 I'm planning to do some client work - just a few hours per week, to take all the financial pressure off my business.&lt;/p&gt;

&lt;p&gt;And I'll focus on creating new, high-value content across all my platforms.&lt;/p&gt;

&lt;p&gt;I still want to set some goal-posts for my business. Here they are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Reach $6,000 MAR&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;200K pageviews / 50K unique visitors per month on my website&lt;/li&gt;
&lt;li&gt;Grow my newsletter to 10K subscribers&lt;/li&gt;
&lt;li&gt;Grow to 100K views per month on YouTube, 40K subscribers&lt;/li&gt;
&lt;li&gt;Double Twitter followers to 10K&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In honesty I don't think I have even a &lt;strong&gt;remote&lt;/strong&gt; chance of meeting all these goals in 2021. &lt;/p&gt;

&lt;p&gt;But I'll try and if I only get there the year after, that is cool with me. 🙂&lt;/p&gt;

&lt;p&gt;I still need to figure out what I can do to unlock the next level of growth. But this is the nature of running a business, and I want to enjoy the journey. ⛰&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrap Up
&lt;/h2&gt;

&lt;p&gt;If you're a content creator or want to become one, I hope this article was helpful.&lt;/p&gt;

&lt;p&gt;If you are one of my students, thanks ever so much for being part of my journey.&lt;/p&gt;

&lt;p&gt;Whether you've been on my website before or this is the first article you read here, I hope you'll come back. &lt;/p&gt;

&lt;p&gt;If you have any feedback, you can ping me &lt;a href="https://twitter.com/biz84" rel="noopener noreferrer"&gt;on Twitter&lt;/a&gt; or leave a comment below. 👇&lt;/p&gt;

&lt;p&gt;Thanks for reading, and I wish you all the best in 2021!&lt;/p&gt;

</description>
      <category>contentcreation</category>
      <category>business</category>
    </item>
    <item>
      <title>Top 16 Dart Tips and Tricks Every Flutter Developer Should Know</title>
      <dc:creator>Andrea Bizzotto</dc:creator>
      <pubDate>Thu, 19 Nov 2020 22:04:49 +0000</pubDate>
      <link>https://dev.to/biz84/top-16-dart-tips-and-tricks-every-flutter-developer-should-know-3ah3</link>
      <guid>https://dev.to/biz84/top-16-dart-tips-and-tricks-every-flutter-developer-should-know-3ah3</guid>
      <description>&lt;p&gt;&lt;em&gt;NOTE: This tutorial is also available as a &lt;a href="https://youtu.be/9OxxU4RlCkk"&gt;video on YouTube&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In this tutorial, I share my top Dart tips and tricks that will improve your coding style as a Flutter developer.&lt;/p&gt;

&lt;p&gt;You can use them to write more concise and effective code, and make the most of the Dart language.&lt;/p&gt;

&lt;p&gt;Ready? Let's get started!&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Did you know? Dart supports string multiplication.
&lt;/h2&gt;

&lt;p&gt;Here is a simple program showing how to print a Christmas tree with string multiplication:&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="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="o"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;print&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'🎄'&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="c1"&gt;// Output:&lt;/span&gt;
&lt;span class="c1"&gt;// 🎄&lt;/span&gt;
&lt;span class="c1"&gt;// 🎄🎄&lt;/span&gt;
&lt;span class="c1"&gt;// 🎄🎄🎄&lt;/span&gt;
&lt;span class="c1"&gt;// 🎄🎄🎄🎄&lt;/span&gt;
&lt;span class="c1"&gt;// 🎄🎄🎄🎄🎄&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Cool isn't it? 😉&lt;/p&gt;

&lt;p&gt;You can use this to check how a long string fits inside a &lt;code&gt;Text&lt;/code&gt; widget:&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;Text&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'You have pushed the button this many times:'&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  2. Need to execute multiple Futures concurrently? Use Future.wait.
&lt;/h2&gt;

&lt;p&gt;Consider this mock API class that tells us the latest numbers of COVID cases:&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;// Mock API class&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CovidAPI&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;Future&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;getCases&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Future&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="mi"&gt;1000&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
  &lt;span class="n"&gt;Future&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;getRecovered&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Future&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="mi"&gt;100&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
  &lt;span class="n"&gt;Future&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;getDeaths&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Future&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="mi"&gt;10&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To execute all these futures concurrently, use &lt;code&gt;Future.wait&lt;/code&gt;. This takes a &lt;strong&gt;list or futures&lt;/strong&gt; and returns a &lt;strong&gt;future of lists&lt;/strong&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;api&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;CovidAPI&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;values&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;await&lt;/span&gt; &lt;span class="n"&gt;Future&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;wait&lt;/span&gt;&lt;span class="o"&gt;([&lt;/span&gt;
    &lt;span class="n"&gt;api&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getCases&lt;/span&gt;&lt;span class="o"&gt;(),&lt;/span&gt;
    &lt;span class="n"&gt;api&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getRecovered&lt;/span&gt;&lt;span class="o"&gt;(),&lt;/span&gt;
    &lt;span class="n"&gt;api&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getDeaths&lt;/span&gt;&lt;span class="o"&gt;(),&lt;/span&gt;
&lt;span class="o"&gt;]);&lt;/span&gt;
&lt;span class="n"&gt;print&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;values&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// [1000, 100, 10]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is ideal when the futures are &lt;strong&gt;independent&lt;/strong&gt;, and they don't need to execute &lt;strong&gt;sequentially&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Implement a "call" method in your Dart classes to make them callable like a function.
&lt;/h2&gt;

&lt;p&gt;Here's an example &lt;code&gt;PasswordValidator&lt;/code&gt; class:&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;PasswordValidator&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;call&lt;/span&gt;&lt;span class="o"&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="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;length&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Because the method is named &lt;code&gt;call&lt;/code&gt;, we can declare a class instance and use it &lt;strong&gt;as if&lt;/strong&gt; it was a method:&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;validator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;PasswordValidator&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="c1"&gt;// can use it like this:&lt;/span&gt;
&lt;span class="n"&gt;validator&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'test'&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;validator&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'test1234'&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// no need to use it like this:&lt;/span&gt;
&lt;span class="n"&gt;validator&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;call&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'not-so-frozen-arctic'&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  4. Need to invoke a callback but only if it's not null? Use the "?.call()" syntax.
&lt;/h2&gt;

&lt;p&gt;Suppose we have a custom widget class that should call an &lt;code&gt;onDragCompleted&lt;/code&gt; callback when a certain event takes place:&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;CustomDraggable&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="n"&gt;StatelessWidget&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;CustomDraggable&lt;/span&gt;&lt;span class="o"&gt;({&lt;/span&gt;&lt;span class="n"&gt;Key&lt;/span&gt; &lt;span class="n"&gt;key&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="na"&gt;onDragCompleted&lt;/span&gt;&lt;span class="o"&gt;})&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;key:&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;VoidCallback&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="n"&gt;onDragCompleted&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

  &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="n"&gt;_dragComplete&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// TODO: Implement me&lt;/span&gt;
  &lt;span class="o"&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="o"&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="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/*...*/&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To invoke the callback, we could write this code:&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="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;_dragComplete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;onDragCompleted&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;onDragCompleted&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But there is a simpler way (note the use of &lt;code&gt;?.&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;Future&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;_dragComplete&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="n"&gt;async&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;onDragCompleted&lt;/span&gt;&lt;span class="o"&gt;?.&lt;/span&gt;&lt;span class="na"&gt;call&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  5. Using anonymous functions and functions as arguments
&lt;/h2&gt;

&lt;p&gt;In Dart, functions are &lt;strong&gt;first-class citizens&lt;/strong&gt;, and can be passed &lt;strong&gt;as arguments&lt;/strong&gt; to other functions.&lt;/p&gt;

&lt;p&gt;Here is some code that defines an anonymous function and assigns it to a &lt;code&gt;sayHi&lt;/code&gt; variable:&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="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="o"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;sayHi&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s"&gt;'Hi, &lt;/span&gt;&lt;span class="si"&gt;$name&lt;/span&gt;&lt;span class="s"&gt;'&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
  &lt;span class="n"&gt;welcome&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sayHi&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'Andrea'&lt;/span&gt;&lt;span class="o"&gt;);&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;welcome&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;Function&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="n"&gt;greet&lt;/span&gt;&lt;span class="o"&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="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;print&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;greet&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;
  &lt;span class="n"&gt;print&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'Welcome to this course'&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then &lt;code&gt;sayHi&lt;/code&gt; is passed to a &lt;code&gt;welcome&lt;/code&gt; function that takes a &lt;code&gt;Function&lt;/code&gt; argument and uses it to greet the user.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;String Function(String)&lt;/code&gt; is a &lt;strong&gt;function type&lt;/strong&gt; that takes a &lt;code&gt;String&lt;/code&gt; argument and returns a &lt;code&gt;String&lt;/code&gt;. Because the anonymous function above has the same &lt;strong&gt;signature&lt;/strong&gt;, it can be passed directly as an argument, or via the &lt;code&gt;sayHi&lt;/code&gt; variable.&lt;/p&gt;




&lt;p&gt;This coding style is common when using functional operators such as &lt;code&gt;map&lt;/code&gt;, &lt;code&gt;where&lt;/code&gt;, and &lt;code&gt;reduce&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;For example, here's a simple function to calculate the square of a number:&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="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;square&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// just a simple example&lt;/span&gt;
  &lt;span class="c1"&gt;// could be a complex function with a lot of code&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Given a list of values, we can map over them to get the squares:&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;const&lt;/span&gt; &lt;span class="n"&gt;values&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="o"&gt;];&lt;/span&gt;

&lt;span class="n"&gt;values&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;map&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;square&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;toList&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here we pass &lt;code&gt;square&lt;/code&gt; as an argument, because its signature is exactly what the map operator expects. This means that we don't need to expand it with an anonymous function:&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;values&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;map&lt;/span&gt;&lt;span class="o"&gt;((&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;square&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="o"&gt;)).&lt;/span&gt;&lt;span class="na"&gt;toList&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  6. You can use collection-if and spreads with lists, sets AND maps
&lt;/h2&gt;

&lt;p&gt;Collection-if and spreads are very useful when you write your UI as code.&lt;/p&gt;

&lt;p&gt;But did you know that you can use them with maps as well?&lt;/p&gt;

&lt;p&gt;Consider this 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;const&lt;/span&gt; &lt;span class="n"&gt;addRatings&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;restaurant&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="s"&gt;'name'&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;'Pizza Mario'&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
  &lt;span class="s"&gt;'cuisine'&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;'Italian'&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;addRatings&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;...{&lt;/span&gt;
    &lt;span class="s"&gt;'avgRating'&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;4.3&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;'numRatings'&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here we're declaring a &lt;code&gt;restaurant&lt;/code&gt; map, and only adding the &lt;code&gt;avgRating&lt;/code&gt; and &lt;code&gt;numRatings&lt;/code&gt; key-value pairs if &lt;code&gt;addRatings&lt;/code&gt; is &lt;code&gt;true&lt;/code&gt;. And because we're adding more than one key-value pair, we need to use the spread operator (&lt;code&gt;...&lt;/code&gt;).&lt;/p&gt;

&lt;h2&gt;
  
  
  7. Need to iterate through a map in a null-safe manner? Use &lt;code&gt;.entries&lt;/code&gt;:
&lt;/h2&gt;

&lt;p&gt;Suppose you have this map:&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;const&lt;/span&gt; &lt;span class="n"&gt;timeSpent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;double&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;{&lt;/span&gt;
  &lt;span class="s"&gt;'Blogging'&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;10.5&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
  &lt;span class="s"&gt;'YouTube'&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;30.5&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
  &lt;span class="s"&gt;'Courses'&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;75.2&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
&lt;span class="o"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here's how you can write a loop to run some code using all the key-value pairs:&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="k"&gt;for&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="n"&gt;entry&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;timeSpent&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;entries&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// do something with keys and values&lt;/span&gt;
  &lt;span class="n"&gt;print&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'&lt;/span&gt;&lt;span class="si"&gt;${entry.key}&lt;/span&gt;&lt;span class="s"&gt;: &lt;/span&gt;&lt;span class="si"&gt;${entry.value}&lt;/span&gt;&lt;span class="s"&gt;'&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By iterating on the &lt;code&gt;entries&lt;/code&gt; variable, you have access to all the key-value pairs &lt;strong&gt;in a null-safe way&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;This is more concise and less error-prone than 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="k"&gt;for&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;timeSpent&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;keys&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;timeSpent&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="o"&gt;]!;&lt;/span&gt;
  &lt;span class="n"&gt;print&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'&lt;/span&gt;&lt;span class="si"&gt;$key&lt;/span&gt;&lt;span class="s"&gt;: &lt;/span&gt;&lt;span class="si"&gt;$value&lt;/span&gt;&lt;span class="s"&gt;'&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The code above requires to use the assertion operator (&lt;code&gt;!&lt;/code&gt;) when reading the values, as Dart can't guarantee that a value exists for a given key.&lt;/p&gt;

&lt;h2&gt;
  
  
  8. Use named constructors and initializer lists for more ergonomic APIs.
&lt;/h2&gt;

&lt;p&gt;Suppose that you want to declare a class that represents a temperature value.&lt;/p&gt;

&lt;p&gt;You can make your class API unambiguous and support &lt;strong&gt;both&lt;/strong&gt; Celsius and Fahrenheit with two named constructors:&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;Temperature&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;Temperature&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;celsius&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="na"&gt;celsius&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
  &lt;span class="n"&gt;Temperature&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;fahrenheit&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;fahrenheit&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;celsius&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fahrenheit&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mf"&gt;1.8&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
  &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;celsius&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This class only needs one &lt;strong&gt;stored&lt;/strong&gt; variable to represent the temperature and uses an initializer list to convert Fahrenheit to Celsius.&lt;/p&gt;

&lt;p&gt;This means that you can declare temperature values 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="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;temp1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Temperature&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;celsius&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;temp2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Temperature&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;fahrenheit&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;90&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  9. Getters and setters
&lt;/h2&gt;

&lt;p&gt;In the &lt;code&gt;Temperature&lt;/code&gt; class above, &lt;code&gt;celsius&lt;/code&gt; is declared as a stored variable.&lt;/p&gt;

&lt;p&gt;But users may prefer to &lt;strong&gt;get&lt;/strong&gt; or &lt;strong&gt;set&lt;/strong&gt; the temperature in Fahrenheit.&lt;/p&gt;

&lt;p&gt;This is easily done with getters and setters, that allow you to define computed variables. Here's the updated class:&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;Temperature&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;Temperature&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;celsius&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="na"&gt;celsius&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
  &lt;span class="n"&gt;Temperature&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;fahrenheit&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;fahrenheit&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;celsius&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fahrenheit&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mf"&gt;1.8&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
  &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;celsius&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
  &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="kd"&gt;get&lt;/span&gt; &lt;span class="n"&gt;fahrenheit&lt;/span&gt;
    &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;celsius&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mf"&gt;1.8&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;set&lt;/span&gt; &lt;span class="n"&gt;fahrenheit&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;fahrenheit&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;celsius&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fahrenheit&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mf"&gt;1.8&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This makes it easy to get or set the temperature with either Fahrenheit or Celsius:&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;temp1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Temperature&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;celsius&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;print&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;temp1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;fahrenheit&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;temp2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Temperature&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;fahrenheit&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;90&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;temp2&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;celsius&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;28&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Bottom line&lt;/strong&gt;: use named constructors, getters and setters to improve the design of your classes.&lt;/p&gt;

&lt;h2&gt;
  
  
  10. Use underscores for unused function arguments
&lt;/h2&gt;

&lt;p&gt;In Flutter we often use widgets that take function arguments. One common example of this is &lt;code&gt;ListView.builder&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;class&lt;/span&gt; &lt;span class="nc"&gt;MyListView&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="n"&gt;StatelessWidget&lt;/span&gt; &lt;span class="o"&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="o"&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="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;ListView&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;builder&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
      &lt;span class="nl"&gt;itemBuilder:&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;ListTile&lt;/span&gt;&lt;span class="o"&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="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'all the same'&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt;
      &lt;span class="o"&gt;),&lt;/span&gt;
      &lt;span class="nl"&gt;itemCount:&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
    &lt;span class="o"&gt;);&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this case, we are not using the &lt;code&gt;(context, index)&lt;/code&gt; arguments in the &lt;code&gt;itemBuilder&lt;/code&gt;. So we can replace them with underscores instead:&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="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;builder&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
  &lt;span class="nl"&gt;itemBuilder:&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;__&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;ListTile&lt;/span&gt;&lt;span class="o"&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="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'all the same'&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt;
  &lt;span class="o"&gt;),&lt;/span&gt;
  &lt;span class="nl"&gt;itemCount:&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Note: the two arguments are different (`&lt;/em&gt;&lt;code&gt; and &lt;/code&gt;_&lt;em&gt;`) as they are &lt;strong&gt;separate identifiers&lt;/strong&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  11. Need a class that can only be instantiated once (aka singleton)? Use a static instance variable with a private constructor.
&lt;/h2&gt;

&lt;p&gt;The most important property of a singleton is that there can only be &lt;strong&gt;one instance&lt;/strong&gt; of it in your entire program. This is useful to model things like a file system.&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;// file_system.dart&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;FileSystem&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;FileSystem&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;_&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
  &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;instance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;FileSystem&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;_&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To create a singleton in Dart you can declare a named constructor and make it private using the &lt;code&gt;_&lt;/code&gt; syntax.&lt;/p&gt;

&lt;p&gt;Then you can use it to create one static final instance of your class.&lt;/p&gt;

&lt;p&gt;And as a result, any code in other files will only be able to access this class via the &lt;code&gt;instance&lt;/code&gt; variable:&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;// some_other_file.dart&lt;/span&gt;
&lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;fs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;FileSystem&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;instance&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;// do something with fs&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Note: Singletons can lead to many problems if you're not careful. Make sure you understand the disadvantages before using them.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  12. Need a collection of unique items? Use a Set rather than a List.
&lt;/h2&gt;

&lt;p&gt;The most commonly used collection type in Dart is a &lt;code&gt;List&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;But lists can have duplicate items, and sometimes this is not what we want:&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;const&lt;/span&gt; &lt;span class="n"&gt;citiesList&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;
  &lt;span class="s"&gt;'London'&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
  &lt;span class="s"&gt;'Paris'&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
  &lt;span class="s"&gt;'Rome'&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
  &lt;span class="s"&gt;'London'&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
&lt;span class="o"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can use a &lt;code&gt;Set&lt;/code&gt; whenever we need a collection of unique values (note the use of &lt;code&gt;final&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="c1"&gt;// set is final, compiles&lt;/span&gt;
&lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;citiesSet&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="s"&gt;'London'&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
  &lt;span class="s"&gt;'Paris'&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
  &lt;span class="s"&gt;'Rome'&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
  &lt;span class="s"&gt;'London'&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Two elements in a set literal shouldn't be equal&lt;/span&gt;
&lt;span class="o"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The code above generates a warning because &lt;code&gt;London&lt;/code&gt; is included twice. If we try doing the same with a &lt;code&gt;const&lt;/code&gt; set, we get an error and our code doesn't compile:&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;// set is const, doesn't compile&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;citiesSet&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="s"&gt;'London'&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
  &lt;span class="s"&gt;'Paris'&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
  &lt;span class="s"&gt;'Rome'&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
  &lt;span class="s"&gt;'London'&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Two elements in a constant set literal can't be equal&lt;/span&gt;
&lt;span class="o"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When we work with sets, we have access to useful APIs such as &lt;code&gt;union&lt;/code&gt;, &lt;code&gt;difference&lt;/code&gt;, and &lt;code&gt;intersection&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;citiesSet&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;union&lt;/span&gt;&lt;span class="o"&gt;({&lt;/span&gt;&lt;span class="s"&gt;'Delhi'&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'Moscow'&lt;/span&gt;&lt;span class="o"&gt;});&lt;/span&gt;
&lt;span class="n"&gt;citiesSet&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;difference&lt;/span&gt;&lt;span class="o"&gt;({&lt;/span&gt;&lt;span class="s"&gt;'London'&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'Madrid'&lt;/span&gt;&lt;span class="o"&gt;});&lt;/span&gt;
&lt;span class="n"&gt;citiesSet&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;intersection&lt;/span&gt;&lt;span class="o"&gt;({&lt;/span&gt;&lt;span class="s"&gt;'London'&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'Berlin'&lt;/span&gt;&lt;span class="o"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Bottom line: when you create a collection, ask yourself if you want its items to be unique, and consider using a set.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  13. How to use try, on, catch, rethrow, finally
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;try&lt;/code&gt; and &lt;code&gt;catch&lt;/code&gt; are ideal when working with Future-based APIs that may throw an exception if something goes wrong.&lt;/p&gt;

&lt;p&gt;Here's a full example showing how to make the most of them:&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;Future&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;printWeather&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="n"&gt;async&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;api&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;WeatherApiClient&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;weather&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;await&lt;/span&gt; &lt;span class="n"&gt;api&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getWeather&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'London'&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;print&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;weather&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="n"&gt;on&lt;/span&gt; &lt;span class="n"&gt;SocketException&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;print&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'Could not fetch data. Check your connection.'&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="n"&gt;on&lt;/span&gt; &lt;span class="n"&gt;WeatherApiException&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;print&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;st&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;print&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'Error: &lt;/span&gt;&lt;span class="si"&gt;$e&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;Stack trace: &lt;/span&gt;&lt;span class="si"&gt;$st&lt;/span&gt;&lt;span class="s"&gt;'&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;rethrow&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;finally&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;print&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'Done'&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A few notes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;you can add multiple &lt;code&gt;on&lt;/code&gt; clauses to handle exceptions of different types.&lt;/li&gt;
&lt;li&gt;you can have a fallback &lt;code&gt;catch&lt;/code&gt; clause to handle all exceptions that do not match any of the types above.&lt;/li&gt;
&lt;li&gt;you can use a &lt;code&gt;rethrow&lt;/code&gt; statement to throw the current exception up the call stack &lt;strong&gt;while preserving the stack trace&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;you can use &lt;code&gt;finally&lt;/code&gt; to run some code after the &lt;code&gt;Future&lt;/code&gt; has completed, regardless of whether it succeeded or failed.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you are using or designing some Future-based APIs, make sure to handle exceptions as needed.&lt;/p&gt;

&lt;h2&gt;
  
  
  14. Common Future constructors
&lt;/h2&gt;

&lt;p&gt;The Dart &lt;code&gt;Future&lt;/code&gt; class comes with some handy factory constructors: &lt;code&gt;Future.delayed&lt;/code&gt;, &lt;code&gt;Future.value&lt;/code&gt; and &lt;code&gt;Future.error&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;We can use &lt;code&gt;Future.delayed&lt;/code&gt; to create a &lt;code&gt;Future&lt;/code&gt; that waits for a certain delay. The second argument is an (optional) anonymous function that you can use to complete with a value or throw an error:&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;await&lt;/span&gt; &lt;span class="n"&gt;Future&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;delayed&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Duration&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;seconds:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt; &lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s"&gt;'Latte'&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But sometimes we want to create a &lt;code&gt;Future&lt;/code&gt; that completes immediately:&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;await&lt;/span&gt; &lt;span class="n"&gt;Future&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="s"&gt;'Cappuccino'&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;await&lt;/span&gt; &lt;span class="n"&gt;Future&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Exception&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'Out of milk'&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can use &lt;code&gt;Future.value&lt;/code&gt; to complete successfully with a value, or &lt;code&gt;Future.error&lt;/code&gt; to complete with an error.&lt;/p&gt;

&lt;p&gt;You can use these constructors to simulate the response from your Future-based APIs. This is useful when writing mock classes in your test code.&lt;/p&gt;

&lt;h2&gt;
  
  
  15. Common Stream constructors
&lt;/h2&gt;

&lt;p&gt;The Stream class also comes with some handy constructors. Here are the most common ones:&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;Stream&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;fromIterable&lt;/span&gt;&lt;span class="o"&gt;([&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="o"&gt;]);&lt;/span&gt;
&lt;span class="n"&gt;Stream&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="mi"&gt;10&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;Stream&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;empty&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="n"&gt;Stream&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Exception&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'something went wrong'&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;
&lt;span class="n"&gt;Stream&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;fromFuture&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Future&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;delayed&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Duration&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;seconds:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt; &lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;
&lt;span class="n"&gt;Stream&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;periodic&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Duration&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;seconds:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;use &lt;code&gt;Stream.fromIterable&lt;/code&gt; to create a &lt;code&gt;Stream&lt;/code&gt; from a list of values.&lt;/li&gt;
&lt;li&gt;use &lt;code&gt;Stream.value&lt;/code&gt; if you have just one value.&lt;/li&gt;
&lt;li&gt;use &lt;code&gt;Stream.empty&lt;/code&gt; to create an empty stream.&lt;/li&gt;
&lt;li&gt;use &lt;code&gt;Stream.error&lt;/code&gt; to create a stream that contains an error value.&lt;/li&gt;
&lt;li&gt;use &lt;code&gt;Stream.fromFuture&lt;/code&gt; to create a stream that will contain only one value, and that value will be available when the future completes.&lt;/li&gt;
&lt;li&gt;use &lt;code&gt;Stream.periodic&lt;/code&gt; to create a periodic stream of events. You can specify a &lt;code&gt;Duration&lt;/code&gt; as the time interval between events, and an anonymous function to generate each value given its index in the stream.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  16. Sync and Async Generators
&lt;/h2&gt;

&lt;p&gt;In Dart we can define a &lt;strong&gt;synchronous&lt;/strong&gt; generator as a function that returns an &lt;code&gt;Iterable&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;Iterable&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="n"&gt;sync&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;yield&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This uses the &lt;code&gt;sync*&lt;/code&gt; syntax. Inside the function we can "generate" or &lt;code&gt;yield&lt;/code&gt; multiple values. These will be returned as an &lt;code&gt;Iterable&lt;/code&gt; when the function completes.&lt;/p&gt;




&lt;p&gt;On the other hand, an &lt;strong&gt;asynchronous&lt;/strong&gt; generator is a function that returns a &lt;code&gt;Stream&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;Stream&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;countStream&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="n"&gt;async&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;yield&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This uses this &lt;code&gt;async*&lt;/code&gt; syntax. Inside the function we can &lt;code&gt;yield&lt;/code&gt; values just like in the synchronous case.&lt;/p&gt;

&lt;p&gt;But if we want we can &lt;code&gt;await&lt;/code&gt; on Future-based APIs, because this is an &lt;strong&gt;asynchronous&lt;/strong&gt; generator:&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;Stream&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;countStream&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="n"&gt;async&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// dummy delay - this could be a network request&lt;/span&gt;
    &lt;span class="n"&gt;await&lt;/span&gt; &lt;span class="n"&gt;Future&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;delayed&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Duration&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;seconds:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;
    &lt;span class="n"&gt;yield&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;I hope you have enjoyed my top Dart tips and tricks for Flutter developers.&lt;/p&gt;

&lt;p&gt;My challenge for you?&lt;/p&gt;

&lt;p&gt;Use them to improve the code in your Flutter apps. And let me know which was your favourite &lt;a href="https://twitter.com/biz84"&gt;on Twitter&lt;/a&gt;. 😉&lt;/p&gt;

&lt;p&gt;By the way, I shared many more Dart tips &lt;a href="https://twitter.com/search?q=from%3Abiz84%20Easy%20Win&amp;amp;src=typed_query&amp;amp;f=live"&gt;on Twitter&lt;/a&gt;, and also republished them on this website:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://codewithandrea.com/tips/2020-08-09-dart-flutter-easy-wins-1-7/"&gt;Dart &amp;amp; Flutter Easy Wins 1-7&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://codewithandrea.com/tips/2020-08-13-dart-flutter-easy-wins-8-14/"&gt;Dart &amp;amp; Flutter Easy Wins 8-14&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://codewithandrea.com/tips/2020-08-16-dart-flutter-easy-wins-15-21/"&gt;Dart &amp;amp; Flutter Easy Wins 15-21&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://codewithandrea.com/tips/2020-08-23-dart-flutter-easy-wins-22-28/"&gt;Dart &amp;amp; Flutter Easy Wins 22-28&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://codewithandrea.com/tips/2020-08-30-dart-flutter-easy-wins-29-35/"&gt;Dart &amp;amp; Flutter Easy Wins 29-35&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://codewithandrea.com/tips/2020-09-13-dart-flutter-easy-wins-36-42/"&gt;Dart &amp;amp; Flutter Easy Wins 36-42&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Complete Dart Course
&lt;/h2&gt;

&lt;p&gt;If you're new to Dart &amp;amp; Flutter or you want to improve your knowledge of the Dart language, you can buy my &lt;a href="https://nnbd.me/dart"&gt;complete Dart course on Udemy&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;With 10 hours of content, it covers the most important features of the Dart language. It includes exercises, solutions, and practical projects that will help you build your confidence with Dart.&lt;/p&gt;

&lt;p&gt;You can buy the course for a discounted price &lt;a href="https://nnbd.me/dart"&gt;with this link&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Happy coding!&lt;/p&gt;

</description>
      <category>dart</category>
      <category>flutter</category>
    </item>
    <item>
      <title>Dart &amp; Flutter Easy Wins 36-42</title>
      <dc:creator>Andrea Bizzotto</dc:creator>
      <pubDate>Sun, 13 Sep 2020 08:12:03 +0000</pubDate>
      <link>https://dev.to/biz84/dart-flutter-easy-wins-36-42-5e8j</link>
      <guid>https://dev.to/biz84/dart-flutter-easy-wins-36-42-5e8j</guid>
      <description>&lt;p&gt;I recently started a series of &lt;a href="https://twitter.com/search?q=from%3Abiz84%20Easy%20Win&amp;amp;src=typed_query&amp;amp;f=live"&gt;daily tweets&lt;/a&gt; about easy ways to improve your Dart &amp;amp; Flutter code. I called this &lt;strong&gt;Easy Wins&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;To make these easier to find, I'm sharing 7 tips every week here.&lt;/p&gt;

&lt;h2&gt;
  
  
  36. Use &lt;code&gt;Timer.periodic&lt;/code&gt; to create a timer that repeats with a given period
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--jB2RIqYW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://codewithandrea.com/tips/2020-09-13-dart-flutter-easy-wins-36-42/images/036.timer.periodic.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--jB2RIqYW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://codewithandrea.com/tips/2020-09-13-dart-flutter-easy-wins-36-42/images/036.timer.periodic.png" alt="Use Timer.periodic to create a timer that repeats with a given period"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  37. Need to convert an enum to an int or viceversa? Use &lt;code&gt;.index&lt;/code&gt; and &lt;code&gt;values[i]&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--RYNgqyTF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://codewithandrea.com/tips/2020-09-13-dart-flutter-easy-wins-36-42/images/037.enum-index-values.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--RYNgqyTF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://codewithandrea.com/tips/2020-09-13-dart-flutter-easy-wins-36-42/images/037.enum-index-values.png" alt="Need to convert an enum to an int or viceversa? Use .index and values\[i\]"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  38. Use asserts to disrupt program execution if a boolean condition is false
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--J9hbLs6E--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://codewithandrea.com/tips/2020-09-13-dart-flutter-easy-wins-36-42/images/038-assertion.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--J9hbLs6E--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://codewithandrea.com/tips/2020-09-13-dart-flutter-easy-wins-36-42/images/038-assertion.png" alt="Use asserts to disrupt program execution if a boolean condition is false"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  39. Need a better logger for your apps? Use the logger package
&lt;/h2&gt;

&lt;p&gt;Link: &lt;a href="https://pub.dev/packages/logger"&gt;Logger package&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--WGlonnzS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://codewithandrea.com/tips/2020-09-13-dart-flutter-easy-wins-36-42/images/039.logger.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--WGlonnzS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://codewithandrea.com/tips/2020-09-13-dart-flutter-easy-wins-36-42/images/039.logger.png" alt="Need a better logger for your apps? Use the logger package"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  40. Use the Flutter DevTools to inspect and profile your Flutter apps
&lt;/h2&gt;

&lt;p&gt;More info &amp;amp; installation instructions here: &lt;a href="https://flutter.dev/docs/development/tools/devtools/overview"&gt;Flutter DevTools&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--h3e4YUBH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://codewithandrea.com/tips/2020-09-13-dart-flutter-easy-wins-36-42/images/040-dev-tools.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--h3e4YUBH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://codewithandrea.com/tips/2020-09-13-dart-flutter-easy-wins-36-42/images/040-dev-tools.png" alt="Use the Flutter DevTools to inspect and profile your Flutter apps"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  41. Anonymous functions can be assigned to variables, or passed as arguments to other functions
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--mqyTLk2l--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://codewithandrea.com/tips/2020-09-13-dart-flutter-easy-wins-36-42/images/041-anonymous-functions.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--mqyTLk2l--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://codewithandrea.com/tips/2020-09-13-dart-flutter-easy-wins-36-42/images/041-anonymous-functions.png" alt="Anonymous functions can be assigned to variables, or passed as arguments to other functions"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  42. Want a function that can only throw? Use Never
&lt;/h2&gt;

&lt;p&gt;More info here: &lt;a href="https://dart.dev/null-safety/understanding-null-safety#never-for-unreachable-code"&gt;Never for unreachable code&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--NyLZO-ZS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://codewithandrea.com/tips/2020-09-13-dart-flutter-easy-wins-36-42/images/042-never-throw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--NyLZO-ZS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://codewithandrea.com/tips/2020-09-13-dart-flutter-easy-wins-36-42/images/042-never-throw.png" alt="Want a function that can only throw? Use Never"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;More tips coming next week. &lt;a href="https://codewithandrea.com/rss.xml"&gt;Subscribe via RSS&lt;/a&gt; for updates!&lt;/p&gt;

&lt;p&gt;Happy coding!&lt;/p&gt;

</description>
      <category>flutter</category>
      <category>dart</category>
    </item>
    <item>
      <title>Dart &amp; Flutter Easy Wins 29-35</title>
      <dc:creator>Andrea Bizzotto</dc:creator>
      <pubDate>Sun, 13 Sep 2020 08:06:03 +0000</pubDate>
      <link>https://dev.to/biz84/dart-flutter-easy-wins-29-35-535e</link>
      <guid>https://dev.to/biz84/dart-flutter-easy-wins-29-35-535e</guid>
      <description>&lt;p&gt;I recently started a series of &lt;a href="https://twitter.com/search?q=from%3Abiz84%20Easy%20Win&amp;amp;src=typed_query&amp;amp;f=live" rel="noopener noreferrer"&gt;daily tweets&lt;/a&gt; about easy ways to improve your Dart &amp;amp; Flutter code. I called this &lt;strong&gt;Easy Wins&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;To make these easier to find, I'm sharing 7 tips every week here.&lt;/p&gt;

&lt;h2&gt;
  
  
  29. When EXTENDING classes, all ABSTRACT methods MUST be overridden &amp;amp; other methods CAN be overridden. When IMPLEMENTING classes, ALL methods MUST be overridden.
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcodewithandrea.com%2Ftips%2F2020-08-30-dart-flutter-easy-wins-29-35%2Fimages%2F029-extends-vs-implements.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcodewithandrea.com%2Ftips%2F2020-08-30-dart-flutter-easy-wins-29-35%2Fimages%2F029-extends-vs-implements.png" alt="When EXTENDING classes, all ABSTRACT methods MUST be overridden &amp;amp; other methods CAN be overridden. When IMPLEMENTING classes, ALL methods MUST be overridden."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  30. Need to iterate through a map in a null-safe manner? Use &lt;code&gt;.entries&lt;/code&gt;:
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcodewithandrea.com%2Ftips%2F2020-08-30-dart-flutter-easy-wins-29-35%2Fimages%2F030-map-entries.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcodewithandrea.com%2Ftips%2F2020-08-30-dart-flutter-easy-wins-29-35%2Fimages%2F030-map-entries.png" alt="Need to iterate through a map in a null-safe manner? Use .entries"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  31. Need different implementations for web and native platforms? Use conditional imports.
&lt;/h2&gt;

&lt;p&gt;More info here: &lt;a href="https://dart.dev/guides/libraries/create-library-packages#conditionally-importing-and-exporting-library-files" rel="noopener noreferrer"&gt;Conditionally importing and exporting library files&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcodewithandrea.com%2Ftips%2F2020-08-30-dart-flutter-easy-wins-29-35%2Fimages%2F031-conditional-imports.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcodewithandrea.com%2Ftips%2F2020-08-30-dart-flutter-easy-wins-29-35%2Fimages%2F031-conditional-imports.png" alt="Need different implementations for web and native platforms? Use conditional imports."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  32. Need to declare a function type with generics? Use a typedef:
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcodewithandrea.com%2Ftips%2F2020-08-30-dart-flutter-easy-wins-29-35%2Fimages%2F032-typedef-function-builder.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcodewithandrea.com%2Ftips%2F2020-08-30-dart-flutter-easy-wins-29-35%2Fimages%2F032-typedef-function-builder.png" alt="Need to declare a function type with generics? Use a typedef"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  33. Need to work with &lt;em&gt;computed&lt;/em&gt; variables? Use getters and setters.
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcodewithandrea.com%2Ftips%2F2020-08-30-dart-flutter-easy-wins-29-35%2Fimages%2F033-getters-setters.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcodewithandrea.com%2Ftips%2F2020-08-30-dart-flutter-easy-wins-29-35%2Fimages%2F033-getters-setters.png" alt="Need to work with *computed* variables? Use getters and setters"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  34. Need to return a Future that returns immediately? Use &lt;code&gt;Future.value&lt;/code&gt;.
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcodewithandrea.com%2Ftips%2F2020-08-30-dart-flutter-easy-wins-29-35%2Fimages%2F034-future-value.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcodewithandrea.com%2Ftips%2F2020-08-30-dart-flutter-easy-wins-29-35%2Fimages%2F034-future-value.png" alt="Need to return a Future that returns immediately? Use Future.value"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  35. Want to force a delay before executing some code? Use &lt;code&gt;Future.delayed&lt;/code&gt;.
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcodewithandrea.com%2Ftips%2F2020-08-30-dart-flutter-easy-wins-29-35%2Fimages%2F035-future-delayed.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcodewithandrea.com%2Ftips%2F2020-08-30-dart-flutter-easy-wins-29-35%2Fimages%2F035-future-delayed.png" alt="Want to force a delay before executing some code? Use Future.delayed"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;More tips coming next week. &lt;a href="https://codewithandrea.com/rss.xml" rel="noopener noreferrer"&gt;Subscribe via RSS&lt;/a&gt; for updates!&lt;/p&gt;

&lt;p&gt;Happy coding!&lt;/p&gt;

</description>
      <category>flutter</category>
      <category>dart</category>
    </item>
    <item>
      <title>Dart &amp; Flutter Easy Wins 22-28</title>
      <dc:creator>Andrea Bizzotto</dc:creator>
      <pubDate>Sun, 23 Aug 2020 14:39:49 +0000</pubDate>
      <link>https://dev.to/biz84/dart-flutter-easy-wins-22-28-1am7</link>
      <guid>https://dev.to/biz84/dart-flutter-easy-wins-22-28-1am7</guid>
      <description>&lt;p&gt;I recently started a series of &lt;a href="https://twitter.com/search?q=from%3Abiz84%20Easy%20Win&amp;amp;src=typed_query&amp;amp;f=live"&gt;daily tweets&lt;/a&gt; about easy ways to improve your Dart &amp;amp; Flutter code. I called this &lt;strong&gt;Easy Wins&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;To make these easier to find, I'm sharing 7 tips every week here.&lt;/p&gt;

&lt;h2&gt;
  
  
  22. Use &lt;code&gt;toStringAsFixed(n)&lt;/code&gt; to format a number with n decimal places.
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--jHtE7F2r--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://codewithandrea.com/tips/2020-08-23-dart-flutter-easy-wins-22-28/images/022-to-string-as-fixed-narrow.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--jHtE7F2r--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://codewithandrea.com/tips/2020-08-23-dart-flutter-easy-wins-22-28/images/022-to-string-as-fixed-narrow.png" alt="Use toStringAsFixed(n) to format a number with n decimal places."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  23. Did you know? Dart supports string multiplication.
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--f0u1kBrw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://codewithandrea.com/tips/2020-08-23-dart-flutter-easy-wins-22-28/images/023.string-multiplication.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--f0u1kBrw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://codewithandrea.com/tips/2020-08-23-dart-flutter-easy-wins-22-28/images/023.string-multiplication.png" alt="Did you know? Dart supports string multiplication."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  24. One constructor is not enough? Use named constructors and initializer lists for more ergonomic APIs.
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--nkhLxaUC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://codewithandrea.com/tips/2020-08-23-dart-flutter-easy-wins-22-28/images/024.named-constructors.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--nkhLxaUC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://codewithandrea.com/tips/2020-08-23-dart-flutter-easy-wins-22-28/images/024.named-constructors.png" alt="One constructor is not enough? Use named constructors and initializer lists for more ergonomic APIs."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  25. Prefer factory constructors to static methods for deserialization.
&lt;/h2&gt;

&lt;p&gt;More info here: &lt;a href="https://dash-overflow.net/articles/factory/"&gt;The difference between a "factory constructor" and a "static method"&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--A9_x6HE8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://codewithandrea.com/tips/2020-08-23-dart-flutter-easy-wins-22-28/images/025.prefer-factory-static.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--A9_x6HE8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://codewithandrea.com/tips/2020-08-23-dart-flutter-easy-wins-22-28/images/025.prefer-factory-static.png" alt="Prefer factory constructors to static methods for deserialization."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  26. Need a class that can only be instantiated once (aka singleton)? Use static instance variable with a private constructor.
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--90ofhsYk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://codewithandrea.com/tips/2020-08-23-dart-flutter-easy-wins-22-28/images/026.singleton-private-constructor.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--90ofhsYk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://codewithandrea.com/tips/2020-08-23-dart-flutter-easy-wins-22-28/images/026.singleton-private-constructor.png" alt="Need a class that can only be instantiated once (aka singleton)? Use static instance variable with a private constructor."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  27. Need a collection of unique items? Use a set rather than a list.
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s---02Qprxc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://codewithandrea.com/tips/2020-08-23-dart-flutter-easy-wins-22-28/images/027-unique-elements-set-list.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s---02Qprxc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://codewithandrea.com/tips/2020-08-23-dart-flutter-easy-wins-22-28/images/027-unique-elements-set-list.png" alt="Need a collection of unique items? Use a set rather than a list."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  28. Use inheritance to model ISA relationships.
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--G8nBN8pk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://codewithandrea.com/tips/2020-08-23-dart-flutter-easy-wins-22-28/images/028-inheritance-ISA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--G8nBN8pk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://codewithandrea.com/tips/2020-08-23-dart-flutter-easy-wins-22-28/images/028-inheritance-ISA.png" alt="Use inheritance to model ISA relationships."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;More tips coming next week. &lt;a href="https://codewithandrea.com/rss.xml"&gt;Subscribe via RSS&lt;/a&gt; for updates!&lt;/p&gt;

&lt;p&gt;Happy coding!&lt;/p&gt;

</description>
      <category>flutter</category>
      <category>dart</category>
    </item>
    <item>
      <title>Dart &amp; Flutter Easy Wins 15-21</title>
      <dc:creator>Andrea Bizzotto</dc:creator>
      <pubDate>Sun, 16 Aug 2020 16:32:04 +0000</pubDate>
      <link>https://dev.to/biz84/dart-flutter-easy-wins-15-21-4ee5</link>
      <guid>https://dev.to/biz84/dart-flutter-easy-wins-15-21-4ee5</guid>
      <description>&lt;p&gt;I recently started a series of &lt;a href="https://twitter.com/search?q=from%3Abiz84%20Easy%20Win&amp;amp;src=typed_query&amp;amp;f=live"&gt;daily tweets&lt;/a&gt; about easy ways to improve your Dart &amp;amp; Flutter code. I called this &lt;strong&gt;Easy Wins&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;To make these easier to find, I'm sharing 7 tips every week here.&lt;/p&gt;

&lt;h2&gt;
  
  
  15. Need to shallow copy a list or collection? Use the spread operator.
&lt;/h2&gt;

&lt;p&gt;More info here: &lt;a href="https://stackoverflow.com/questions/21744480/clone-a-list-map-or-set-in-dart"&gt;Clone a List, Map or Set in Dart | StackOverflow&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--T1g9Goad--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://codewithandrea.com/tips/2020-08-16-dart-flutter-easy-wins-15-21/images/015.shallow-copy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--T1g9Goad--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://codewithandrea.com/tips/2020-08-16-dart-flutter-easy-wins-15-21/images/015.shallow-copy.png" alt="Need to shallow copy a list or collection? Use the spread operator."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  16. Need to invoke a callback but only if it's not null? Use the "?.call()" syntax.
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Pcacobib--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://codewithandrea.com/tips/2020-08-16-dart-flutter-easy-wins-15-21/images/016.callable-functions.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Pcacobib--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://codewithandrea.com/tips/2020-08-16-dart-flutter-easy-wins-15-21/images/016.callable-functions.png" alt="Need to invoke a callback but only if it's not null? Use the &amp;quot;?.call()&amp;quot; syntax."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  17. Implement a "call" method in your Dart classes to make them callable like a function.
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--xwOQbp0n--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://codewithandrea.com/tips/2020-08-16-dart-flutter-easy-wins-15-21/images/017.callable-classes.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--xwOQbp0n--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://codewithandrea.com/tips/2020-08-16-dart-flutter-easy-wins-15-21/images/017.callable-classes.png" alt='Implement a "call" method in your Dart classes to make them callable like a function.'&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  18. Want a more ergonomic API for working with dates and times? Use extensions.
&lt;/h2&gt;

&lt;p&gt;This API and many more are available in the &lt;a href="https://pub.dev/packages/dartx"&gt;dartx package&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Pm8XVS72--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://codewithandrea.com/tips/2020-08-16-dart-flutter-easy-wins-15-21/images/018-duration-extension.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Pm8XVS72--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://codewithandrea.com/tips/2020-08-16-dart-flutter-easy-wins-15-21/images/018-duration-extension.png" alt="Want a more ergonomic API for working with dates and times? Use extensions."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  19. Need to execute multiple Futures concurrently? Use Future.wait.
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--qMTvtvHN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://codewithandrea.com/tips/2020-08-16-dart-flutter-easy-wins-15-21/images/019-future.wait.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--qMTvtvHN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://codewithandrea.com/tips/2020-08-16-dart-flutter-easy-wins-15-21/images/019-future.wait.png" alt="Need to execute multiple Futures concurrently? Use Future.wait."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  20. Want to selectively import some APIs in a package? Use show &amp;amp; hide.
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--mcXtg0dq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://codewithandrea.com/tips/2020-08-16-dart-flutter-easy-wins-15-21/images/020.show-hide.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--mcXtg0dq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://codewithandrea.com/tips/2020-08-16-dart-flutter-easy-wins-15-21/images/020.show-hide.png" alt="Want to selectively import some APIs in a package? Use show &amp;amp; hide."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  21. Use "import as" to avoid name collisions with other packages.
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--bmz7keyB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://codewithandrea.com/tips/2020-08-16-dart-flutter-easy-wins-15-21/images/021.import-as.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--bmz7keyB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://codewithandrea.com/tips/2020-08-16-dart-flutter-easy-wins-15-21/images/021.import-as.png" alt='Use "import as" to avoid name collisions with other packages.'&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;More tips coming next week. &lt;a href="https://codewithandrea.com/rss.xml"&gt;Subscribe via RSS&lt;/a&gt; for updates!&lt;/p&gt;

&lt;p&gt;Happy coding!&lt;/p&gt;

</description>
      <category>dart</category>
      <category>flutter</category>
    </item>
    <item>
      <title>Dart &amp; Flutter Easy Wins 8-14</title>
      <dc:creator>Andrea Bizzotto</dc:creator>
      <pubDate>Thu, 13 Aug 2020 07:42:11 +0000</pubDate>
      <link>https://dev.to/biz84/dart-flutter-easy-wins-8-14-542n</link>
      <guid>https://dev.to/biz84/dart-flutter-easy-wins-8-14-542n</guid>
      <description>&lt;p&gt;I recently started a series of &lt;a href="https://twitter.com/search?q=from%3Abiz84%20Easy%20Win&amp;amp;src=typed_query&amp;amp;f=live"&gt;daily tweets&lt;/a&gt; about easy ways to improve your Dart &amp;amp; Flutter code. I called this &lt;strong&gt;Easy Wins&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;To make these easier to find, I'm sharing 7 tips every week here.&lt;/p&gt;

&lt;h2&gt;
  
  
  8. Use a &lt;code&gt;finally&lt;/code&gt; block for code that should be executed &lt;em&gt;both&lt;/em&gt; on success and failure.
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--n2NsDj1_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://codewithandrea.com/tips/2020-08-13-dart-flutter-easy-wins-8-14/images/008.try-catch-finally.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--n2NsDj1_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://codewithandrea.com/tips/2020-08-13-dart-flutter-easy-wins-8-14/images/008.try-catch-finally.png" alt="Use a `finally` block for code that should be executed **both** on success and failure."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  9. Implement &lt;code&gt;toString()&lt;/code&gt; in your classes to improve the debugging experience.
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--JiH7Sn6P--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://codewithandrea.com/tips/2020-08-13-dart-flutter-easy-wins-8-14/images/009.implement-toString.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--JiH7Sn6P--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://codewithandrea.com/tips/2020-08-13-dart-flutter-easy-wins-8-14/images/009.implement-toString.png" alt="Implement `toString()` in your classes to improve the debugging experience."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  10. Use the if-null operator to provide a fallback for null values.
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--sYVBaG6o--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://codewithandrea.com/tips/2020-08-13-dart-flutter-easy-wins-8-14/images/010.if-null-operator.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--sYVBaG6o--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://codewithandrea.com/tips/2020-08-13-dart-flutter-easy-wins-8-14/images/010.if-null-operator.png" alt="Use the if-null operator to provide a fallback for null values."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  11. Use multi-line strings to represent large blocks of text.
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--2Kx55X-W--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://codewithandrea.com/tips/2020-08-13-dart-flutter-easy-wins-8-14/images/011.multi-line-strings.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--2Kx55X-W--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://codewithandrea.com/tips/2020-08-13-dart-flutter-easy-wins-8-14/images/011.multi-line-strings.png" alt="Use multi-line strings to represent large blocks of text."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  12. String literals can use 'single' or "double" quotes as delimiters. Escape special characters with a backslash (), or use raw strings.
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--mGcpSq0g--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://codewithandrea.com/tips/2020-08-13-dart-flutter-easy-wins-8-14/images/012.string-double-quotes-raw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--mGcpSq0g--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://codewithandrea.com/tips/2020-08-13-dart-flutter-easy-wins-8-14/images/012.string-double-quotes-raw.png" alt="String literals can use single or double quotes as delimiters. Escape special characters with a backslash (\), or use raw strings."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  13. Use triple slashes to generate documentation comments.
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--crFO5Hrm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://codewithandrea.com/tips/2020-08-13-dart-flutter-easy-wins-8-14/images/013-triple-comments.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--crFO5Hrm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://codewithandrea.com/tips/2020-08-13-dart-flutter-easy-wins-8-14/images/013-triple-comments.png" alt="Use triple slashes to generate documentation comments."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  14. Want to auto-generate hashCode, == and toString() implementations for your classes? Use the Equatable package:
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://pub.dev/packages/equatable"&gt;Equatable package&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--VamGO_uk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://codewithandrea.com/tips/2020-08-13-dart-flutter-easy-wins-8-14/images/014.equatable.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--VamGO_uk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://codewithandrea.com/tips/2020-08-13-dart-flutter-easy-wins-8-14/images/014.equatable.png" alt="Want to auto-generate hashCode, == and toString() implementations for your classes? Use the Equatable package:"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;More tips coming next week. &lt;a href="https://codewithandrea.com/rss.xml"&gt;Subscribe via RSS&lt;/a&gt; for updates!&lt;/p&gt;

&lt;p&gt;Happy coding!&lt;/p&gt;

</description>
      <category>flutter</category>
      <category>dart</category>
    </item>
    <item>
      <title>Dart &amp; Flutter Easy Wins 1-7</title>
      <dc:creator>Andrea Bizzotto</dc:creator>
      <pubDate>Sun, 09 Aug 2020 11:50:26 +0000</pubDate>
      <link>https://dev.to/biz84/dart-flutter-easy-wins-1-7-1an9</link>
      <guid>https://dev.to/biz84/dart-flutter-easy-wins-1-7-1an9</guid>
      <description>&lt;p&gt;I recently started a series of &lt;a href="https://twitter.com/search?q=from%3Abiz84%20Easy%20Win&amp;amp;src=typed_query&amp;amp;f=live"&gt;daily tweets&lt;/a&gt; about easy ways to improve your Dart &amp;amp; Flutter code. I called this &lt;strong&gt;Easy Wins&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;To make these easier to find, I'll be sharing 7 tips every week here.&lt;/p&gt;

&lt;p&gt;Without further ado, here are the first 7 tips.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Prefer const over final over var
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--fPeftlD7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://codewithandrea.com/tips/2020-08-09-dart-flutter-easy-wins-1-7/images/001.const-final-var.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--fPeftlD7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://codewithandrea.com/tips/2020-08-09-dart-flutter-easy-wins-1-7/images/001.const-final-var.png" alt="Prefer const over final over var"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Use type annotations for safer code
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--XUnUrT29--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://codewithandrea.com/tips/2020-08-09-dart-flutter-easy-wins-1-7/images/002.type-annotation.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--XUnUrT29--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://codewithandrea.com/tips/2020-08-09-dart-flutter-easy-wins-1-7/images/002.type-annotation.png" alt="Use type annotations for safer code"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Use underscores for unused function arguments
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--69HdryxI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://codewithandrea.com/tips/2020-08-09-dart-flutter-easy-wins-1-7/images/003.underscores_unused_arguments.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--69HdryxI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://codewithandrea.com/tips/2020-08-09-dart-flutter-easy-wins-1-7/images/003.underscores_unused_arguments.png" alt="Use underscores for unused function arguments"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Functions are first class citizens in Dart, and they can be passed directly as arguments
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--jVEWSuwK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://codewithandrea.com/tips/2020-08-09-dart-flutter-easy-wins-1-7/images/004.function-arguments.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--jVEWSuwK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://codewithandrea.com/tips/2020-08-09-dart-flutter-easy-wins-1-7/images/004.function-arguments.png" alt="Functions are first class citizens in Dart, and they can be passed directly as arguments."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  5. You can use collection-if and spreads with lists, sets AND maps
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--dq-iuRZm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://codewithandrea.com/tips/2020-08-09-dart-flutter-easy-wins-1-7/images/005.collection-if-spreads-maps.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--dq-iuRZm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://codewithandrea.com/tips/2020-08-09-dart-flutter-easy-wins-1-7/images/005.collection-if-spreads-maps.png" alt="You can use collection-if and spreads with lists, sets AND maps"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Use the cascade operator to modify mutable variables
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--_iPPaJMk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://codewithandrea.com/tips/2020-08-09-dart-flutter-easy-wins-1-7/images/006.cascade-operator.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--_iPPaJMk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://codewithandrea.com/tips/2020-08-09-dart-flutter-easy-wins-1-7/images/006.cascade-operator.png" alt="Use the cascade operator to modify mutable variables"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  7. You can catch and handle exceptions by type with multiple &lt;code&gt;on&lt;/code&gt; clauses
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--5F1IKjPi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://codewithandrea.com/tips/2020-08-09-dart-flutter-easy-wins-1-7/images/007.catch-exception-by-type.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--5F1IKjPi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://codewithandrea.com/tips/2020-08-09-dart-flutter-easy-wins-1-7/images/007.catch-exception-by-type.png" alt="You can catch and handle exceptions by type with multiple `on` clauses."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;More tips coming next week. &lt;a href="https://codewithandrea.com/rss.xml"&gt;Subscribe via RSS&lt;/a&gt; for updates!&lt;/p&gt;

&lt;p&gt;Happy coding!&lt;/p&gt;

</description>
      <category>flutter</category>
      <category>dart</category>
    </item>
    <item>
      <title>Dart Null Safety: The Ultimate Guide to Non-Nullable Types</title>
      <dc:creator>Andrea Bizzotto</dc:creator>
      <pubDate>Mon, 29 Jun 2020 10:21:06 +0000</pubDate>
      <link>https://dev.to/biz84/dart-null-safety-the-ultimate-guide-to-non-nullable-types-4okm</link>
      <guid>https://dev.to/biz84/dart-null-safety-the-ultimate-guide-to-non-nullable-types-4okm</guid>
      <description>&lt;p&gt;The introduction of Null Safety in Dart 2.9 marks a major milestone for the language. Null Safety helps you avoid an entire class of problems, and enables some performance improvements.&lt;/p&gt;

&lt;p&gt;This article outlines what's changed, and shows how to use the new Null Safety features by example.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;As of June 2020, Null Safety is available in Tech Preview on the Dart &lt;a href="https://dart.dev/get-dart#release-channels"&gt;dev channel&lt;/a&gt;. It's not yet available in the Flutter SDK, but you can try it at &lt;a href="https://nullsafety.dartpad.dev/"&gt;nullsafety.dartpad.dev&lt;/a&gt;:&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--NdwwTCk---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/gwv8m7serv3cx30l8fbd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--NdwwTCk---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/gwv8m7serv3cx30l8fbd.png" alt="Dartpad with Null Safety"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This contains a "Learn from Snippets!" dropdown with mini-exercises to get familiar with the new syntax.&lt;/p&gt;

&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Some context&lt;/li&gt;
&lt;li&gt;Dart Type System&lt;/li&gt;
&lt;li&gt;Dart Null Safety: Benefits&lt;/li&gt;
&lt;li&gt;Declaring Non-Nullable Variables&lt;/li&gt;
&lt;li&gt;Declaring Nullable Variables&lt;/li&gt;
&lt;li&gt;The assertion operator&lt;/li&gt;
&lt;li&gt;Flow Analysis: Promotion&lt;/li&gt;
&lt;li&gt;Flow Analysis: Definite Assignment&lt;/li&gt;
&lt;li&gt;Using non-nullable variables with classes&lt;/li&gt;
&lt;li&gt;Non-nullable named and positional arguments&lt;/li&gt;
&lt;li&gt;Null-aware cascade operator&lt;/li&gt;
&lt;li&gt;Null-aware subscript operator&lt;/li&gt;
&lt;li&gt;The late keyword&lt;/li&gt;
&lt;li&gt;Static and global variables&lt;/li&gt;
&lt;li&gt;Conclusion&lt;/li&gt;
&lt;li&gt;References&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Some context
&lt;/h2&gt;

&lt;p&gt;Null References were &lt;a href="https://www.infoq.com/presentations/Null-References-The-Billion-Dollar-Mistake-Tony-Hoare/"&gt;first introduced&lt;/a&gt; in 1965 in the ALGOL programming language, and since then they have been adopted by most mainstream programming languages.&lt;/p&gt;

&lt;p&gt;However, null errors are so common that null references have been called the The Billion Dollar Mistake.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--G03JDB8Z--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/tpp31119moxe2t8uuz17.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--G03JDB8Z--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/tpp31119moxe2t8uuz17.jpg" alt="Null References Mistake"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So let's see what's changed in Dart to address this.&lt;/p&gt;

&lt;h2&gt;
  
  
  Dart Type System
&lt;/h2&gt;

&lt;p&gt;Before addressing Null Safety, let's talk about the Dart type system.&lt;/p&gt;

&lt;p&gt;Dart is said to have a &lt;strong&gt;sound type system&lt;/strong&gt;. When we write Dart code, the &lt;strong&gt;type checker&lt;/strong&gt; makes sure that we can't write something 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="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;age&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"hello world"&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// A value of type `String` can't be assigned to a variable of type `int`&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This code produces an error telling us that &lt;em&gt;"a &lt;code&gt;String&lt;/code&gt; value can't be assigned to a variable of type &lt;code&gt;int&lt;/code&gt;"&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Similarly, when we write a function in Dart, we can specify a return &lt;strong&gt;type&lt;/strong&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="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;square&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Because of &lt;strong&gt;type safety&lt;/strong&gt;, Dart can guarantee with 100% confidence that this function &lt;strong&gt;always&lt;/strong&gt; returns an &lt;code&gt;int&lt;/code&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Type safety help us write safer programs, and more easily reason about the code.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;But type safety alone can't guarantee that a variable (or return value) is not &lt;code&gt;null&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;As a result this code compiles, but generates an exception &lt;strong&gt;at runtime&lt;/strong&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;square&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// Unhandled Exception: NoSuchMethodError: The method '*' was called on null.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example it's easy enough to spot the problem. But in large codebases it's hard to keep track of what can and cannot be &lt;code&gt;null&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Runtime &lt;code&gt;null&lt;/code&gt; checks can mitigate the problem, but they add more noise:&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="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;square&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;assert&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// for debugging&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="n"&gt;Exception&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What we really want here is to tell Dart that the &lt;code&gt;value&lt;/code&gt; argument should &lt;strong&gt;never&lt;/strong&gt; be &lt;code&gt;null&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;A better solution is needed - and now we have it. 😎&lt;/p&gt;

&lt;h2&gt;
  
  
  Dart Null Safety: Benefits
&lt;/h2&gt;

&lt;p&gt;Dart 2.9 introduces Sound Null Safety as a language feature, and brings three main benefits:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We can write null-safe code with strong &lt;strong&gt;compile-time&lt;/strong&gt; guarantees. This makes us productive because Dart can tell us when we're doing something wrong.&lt;/li&gt;
&lt;li&gt;We can more easily declare our &lt;strong&gt;intent&lt;/strong&gt;. This leads to APIs that are self-documenting and easier to use.&lt;/li&gt;
&lt;li&gt;The Dart compiler can optimise our code, resulting in smaller and faster programs.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So let's see how Null Safety works in practice.&lt;/p&gt;

&lt;h2&gt;
  
  
  Declaring Non-Nullable Variables
&lt;/h2&gt;

&lt;p&gt;The main language change is that all types are now non-nullable &lt;strong&gt;by default&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;This means that this code doesn't compile:&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="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="o"&gt;{&lt;/span&gt;
  &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;age&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// non-nullable&lt;/span&gt;
  &lt;span class="n"&gt;age&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// A value of type `Null` can't be assigned to a variable of type 'int'&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When using non-nullable variables, we must follow one important rule:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Non-nullable variables must always be initialized with non-null values.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If you reason along these lines, it will be easier to understand all the new syntax changes.&lt;/p&gt;




&lt;p&gt;Let's revisit this 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="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;square&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here both the &lt;code&gt;value&lt;/code&gt; argument and the return value are now &lt;strong&gt;guaranteed&lt;/strong&gt; to be not &lt;code&gt;null&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;As a result &lt;strong&gt;runtime&lt;/strong&gt; &lt;code&gt;null&lt;/code&gt; checks are no longer necessary, and this code now produces a &lt;strong&gt;compile-time&lt;/strong&gt; error:&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;square&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// The argument type 'Null' can't be assigned to the parameter type 'int'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But if all types are now &lt;strong&gt;non-nullable&lt;/strong&gt; by default, how can we declare &lt;strong&gt;nullable&lt;/strong&gt; variables?&lt;/p&gt;

&lt;h2&gt;
  
  
  Declaring Nullable Variables
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;?&lt;/code&gt; symbol is what we need:&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="kt"&gt;String&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;  &lt;span class="c1"&gt;// initialized to null by default&lt;/span&gt;
&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="n"&gt;age&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;36&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;  &lt;span class="c1"&gt;// initialized to non-null&lt;/span&gt;
&lt;span class="n"&gt;age&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// can be re-assigned to null&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Note: You don't need to initialize a nullable variable before using it. It is initialized to &lt;code&gt;null&lt;/code&gt; by default.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Here are some other ways of declaring nullable variables:&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;// nullable function argument&lt;/span&gt;
&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;openSocket&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// port can be null&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// nullable return type&lt;/span&gt;
&lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="n"&gt;lastName&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="n"&gt;fullName&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;components&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;fullName&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;split&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;' '&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;components&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;length&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="n"&gt;components&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;last&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// using generics&lt;/span&gt;
&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="n"&gt;firstNonNull&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="o"&gt;?&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// returns first non null element in list if any&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;firstWhere&lt;/span&gt;&lt;span class="o"&gt;((&lt;/span&gt;&lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Take away: you can declare nullable variables &lt;strong&gt;anywhere&lt;/strong&gt; in your code with the &lt;code&gt;?&lt;/code&gt; syntax.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Nullable variables are a good way of expressing the &lt;strong&gt;absence&lt;/strong&gt; of a value, and this is useful in many APIs.&lt;/p&gt;

&lt;p&gt;When you design an API, ask yourself if a variable should be nullable or not, and declare it accordingly.&lt;/p&gt;

&lt;p&gt;But there are cases where we know that something can't be &lt;code&gt;null&lt;/code&gt;, but we can't &lt;strong&gt;prove&lt;/strong&gt; it to the compiler. In these cases, the assertion operator can help.&lt;/p&gt;

&lt;h2&gt;
  
  
  The assertion operator
&lt;/h2&gt;

&lt;p&gt;We can use the assertion operator &lt;code&gt;!&lt;/code&gt; to assign a nullable expression to a non-nullable variable:&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="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="n"&gt;maybeValue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;maybeValue&lt;/span&gt;&lt;span class="o"&gt;!;&lt;/span&gt; &lt;span class="c1"&gt;// valid, value is non-nullable&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By doing this, we're &lt;strong&gt;telling&lt;/strong&gt; Dart that &lt;code&gt;maybeValue&lt;/code&gt; is not &lt;code&gt;null&lt;/code&gt;, and it's safe to assign it to a non-nullable variable.&lt;/p&gt;

&lt;p&gt;Note that applying the assertion operator to a &lt;code&gt;null&lt;/code&gt; value will throw a runtime exception:&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="kt"&gt;String&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;print&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;!);&lt;/span&gt; &lt;span class="c1"&gt;// NoSuchMethodError: '&amp;lt;Unexpected Null Value&amp;gt;'&lt;/span&gt;
&lt;span class="n"&gt;print&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;!);&lt;/span&gt; &lt;span class="c1"&gt;// NoSuchMethodError: '&amp;lt;Unexpected Null Value&amp;gt;'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;When your assumptions are wrong, the &lt;code&gt;!&lt;/code&gt; operator leads to runtime exceptions. &lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;Sometimes we need to work with APIs that return nullable values. Let's revisit the &lt;code&gt;lastName&lt;/code&gt; function:&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="kt"&gt;String&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="n"&gt;lastName&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="n"&gt;fullName&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;components&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;fullName&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;split&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;' '&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;components&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;length&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="n"&gt;components&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;last&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here the type system can't help. If we &lt;strong&gt;know&lt;/strong&gt; that the function &lt;strong&gt;will&lt;/strong&gt; return a non-&lt;code&gt;null&lt;/code&gt; value for a given argument, we should assign it to a non-nullable variable &lt;strong&gt;as soon as possible&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;This is done with the &lt;code&gt;!&lt;/code&gt; operator:&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;// prefer this:&lt;/span&gt;
&lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="n"&gt;last&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;lastName&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'Andrea Bizzotto'&lt;/span&gt;&lt;span class="o"&gt;)!;&lt;/span&gt;
&lt;span class="c1"&gt;// to this:&lt;/span&gt;
&lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="n"&gt;last&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;lastName&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'Andrea Bizzotto'&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In summary:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Try to create non-nullable variables when possible, as these will be &lt;strong&gt;guaranteed&lt;/strong&gt; to be not &lt;code&gt;null&lt;/code&gt; at &lt;strong&gt;compile time&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;If you know that a nullable expression won't be &lt;code&gt;null&lt;/code&gt;, you can assign it to a non-nullable variable with the &lt;code&gt;!&lt;/code&gt; operator.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Flow Analysis: Promotion
&lt;/h2&gt;

&lt;p&gt;Dart can make your life easier by taking into account &lt;code&gt;null&lt;/code&gt; checks on nullable variables:&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="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;absoluteValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;
  &lt;span class="c1"&gt;// if we reach this point, value is non-null&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;abs&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here we use an &lt;code&gt;if&lt;/code&gt; statement to return early if the &lt;code&gt;value&lt;/code&gt; argument is &lt;code&gt;null&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;Beyond that point, &lt;code&gt;value&lt;/code&gt; cannot be &lt;code&gt;null&lt;/code&gt; and is treated (or &lt;strong&gt;promoted&lt;/strong&gt;) to a non-nullable value. Hence we can safely use &lt;code&gt;value.abs()&lt;/code&gt; rather than &lt;code&gt;value?.abs()&lt;/code&gt; (with the null-aware operator).&lt;/p&gt;

&lt;p&gt;Similarly, we could throw an exception if the value is &lt;code&gt;null&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="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;absoluteValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="n"&gt;Exception&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;
  &lt;span class="c1"&gt;// if we reach this point, value is non-null&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;abs&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once again, &lt;code&gt;value&lt;/code&gt; is promoted to a non-nullable value, and the null-aware operator &lt;code&gt;?.&lt;/code&gt; is not needed.&lt;/p&gt;

&lt;p&gt;In summary:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use &lt;strong&gt;upfront&lt;/strong&gt; null checks to return early or throw exceptions&lt;/li&gt;
&lt;li&gt;After null checks, nullable variables are &lt;strong&gt;promoted&lt;/strong&gt; to be non-nullable&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And after a nullable variable has been null checked, Dart lets you use it as a non-nullable variable, which is quite nice.&lt;/p&gt;

&lt;h2&gt;
  
  
  Flow Analysis: Definite Assignment
&lt;/h2&gt;

&lt;p&gt;Dart knows where variables are &lt;strong&gt;assigned&lt;/strong&gt; and where they're &lt;strong&gt;read&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;This example shows how to initialize a non-nullable variable &lt;strong&gt;after&lt;/strong&gt; checking for a condition:&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="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;sign&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// non-nullable&lt;/span&gt;
  &lt;span class="n"&gt;print&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;abs&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt; &lt;span class="c1"&gt;// invalid: 'result' must be assigned before it can be used&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;
  &lt;span class="n"&gt;print&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;abs&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt; &lt;span class="c1"&gt;// ok now&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As long as a non-nullable variable is given a value &lt;strong&gt;before&lt;/strong&gt; it's used, Dart is happy.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using non-nullable variables with classes
&lt;/h2&gt;

&lt;p&gt;Instance variables in classes must be initialized if they are non-nullable:&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;BaseUrl&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="n"&gt;hostName&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Non-nullable instance field 'hostName' must be initialized&lt;/span&gt;

  &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;port&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// ok&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If a non-nullable instance variable can't be initialized with a default value, set it with a constructor:&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;BaseUrl&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;BaseUrl&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="na"&gt;hostName&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
  &lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="n"&gt;hostName&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// now valid&lt;/span&gt;

  &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;port&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// ok&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Non-nullable named and positional arguments
&lt;/h2&gt;

&lt;p&gt;With Null Safety, non-nullable &lt;strong&gt;named&lt;/strong&gt; arguments must always be &lt;strong&gt;required&lt;/strong&gt; or have a &lt;strong&gt;default value&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;This applies to regular methods as well as class constructors:&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="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;printAbs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="o"&gt;})&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;  &lt;span class="c1"&gt;// 'value' can't have a value of null because of its type, and no non-null default value is provided&lt;/span&gt;
  &lt;span class="n"&gt;print&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;abs&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Host&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;Host&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="na"&gt;hostName&lt;/span&gt;&lt;span class="o"&gt;});&lt;/span&gt; &lt;span class="c1"&gt;// 'hostName' can't have a value of null because of its type, and no non-null default value is provided&lt;/span&gt;
  &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="n"&gt;hostName&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can fix the code above with the new &lt;code&gt;required&lt;/code&gt; &lt;strong&gt;modifier&lt;/strong&gt;, which replaces the old &lt;code&gt;@required&lt;/code&gt; &lt;strong&gt;annotation&lt;/strong&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="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;printAbs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="n"&gt;required&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="o"&gt;})&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;print&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;abs&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Host&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;Host&lt;/span&gt;&lt;span class="o"&gt;({&lt;/span&gt;&lt;span class="n"&gt;required&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;hostName&lt;/span&gt;&lt;span class="o"&gt;});&lt;/span&gt;
  &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="n"&gt;hostName&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And when we use the above APIs, Dart can tell us if we're doing something wrong:&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;printAbs&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// The named parameter 'value' is required, but there's no corresponding argument&lt;/span&gt;
&lt;span class="n"&gt;printAbs&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;value:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// The argument type 'Null' can't be assigned to the parameter type 'int'&lt;/span&gt;
&lt;span class="n"&gt;printAbs&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;value:&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// ok&lt;/span&gt;

&lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;host1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Host&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// The named parameter 'hostName' is required, but there's no corresponding argument&lt;/span&gt;
&lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;host2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Host&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;hostName:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// The argument type 'Null' can't be assigned to the parameter type 'String'&lt;/span&gt;
&lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;host3&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Host&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;hostName:&lt;/span&gt; &lt;span class="s"&gt;"example.com"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// ok&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On the flip side, if we use &lt;strong&gt;nullable&lt;/strong&gt; instance variables we can omit the &lt;code&gt;required&lt;/code&gt; modifier (or the default value):&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;Host&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;Host&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="na"&gt;hostName&lt;/span&gt;&lt;span class="o"&gt;});&lt;/span&gt;
  &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="n"&gt;hostName&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// nullable, initialized to `null` by default&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="c1"&gt;// all valid cases&lt;/span&gt;
&lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;host1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Host&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// hostName is null&lt;/span&gt;
&lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;host2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Host&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;hostName:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// hostName is null&lt;/span&gt;
&lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;host3&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Host&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;hostName:&lt;/span&gt; &lt;span class="s"&gt;"example.com"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// hostName is non-null&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Positional&lt;/strong&gt; parameters are subject to the same rules:&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;Host&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;Host&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="na"&gt;hostName&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// ok&lt;/span&gt;
  &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="n"&gt;hostName&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Host&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;Host&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="na"&gt;hostName&lt;/span&gt;&lt;span class="o"&gt;]);&lt;/span&gt; &lt;span class="c1"&gt;// The parameter 'hostName' can't have a value of 'null' because of its type, and no non-null default value is provided&lt;/span&gt;
  &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="n"&gt;hostName&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Host&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;Host&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="na"&gt;hostName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"www.codewithandrea.com"&lt;/span&gt;&lt;span class="o"&gt;]);&lt;/span&gt; &lt;span class="c1"&gt;// ok&lt;/span&gt;
  &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="n"&gt;hostName&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Host&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;Host&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="na"&gt;hostName&lt;/span&gt;&lt;span class="o"&gt;]);&lt;/span&gt; &lt;span class="c1"&gt;// ok&lt;/span&gt;
  &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="n"&gt;hostName&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;&lt;em&gt;Between nullable and non-nullable variables, named and positional arguments, required and default values, there's a lot to take in. If you're confused, remember the golden rule:&lt;/em&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Non-nullable variables must always be initialized with non-null values.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;em&gt;To fully understand all the Null Safety features, practice using them with Dartpad. Dart will tell if you're doing something wrong - so read the error messages carefully.&lt;/em&gt; 🔍&lt;/p&gt;

&lt;h2&gt;
  
  
  Null-aware cascade operator
&lt;/h2&gt;

&lt;p&gt;To deal with Null Safety, the cascade operator now gains a new &lt;code&gt;null&lt;/code&gt;-aware variant: &lt;code&gt;?..&lt;/code&gt;. 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="n"&gt;Path&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;// will not do anything if path is null&lt;/span&gt;
&lt;span class="n"&gt;path&lt;/span&gt;
  &lt;span class="o"&gt;?..&lt;/span&gt;&lt;span class="na"&gt;moveTo&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
  &lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="na"&gt;lineTo&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
  &lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="na"&gt;lineTo&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
  &lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="na"&gt;lineTo&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
  &lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="na"&gt;lineTo&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The cascade operations above will only be executed if &lt;code&gt;path&lt;/code&gt; is not &lt;code&gt;null&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;The null-aware cascade operator can &lt;strong&gt;short-circuit&lt;/strong&gt;, so only one &lt;code&gt;?..&lt;/code&gt; operator is needed at the beginning of the sequence.&lt;/p&gt;

&lt;h2&gt;
  
  
  Null-aware subscript operator
&lt;/h2&gt;

&lt;p&gt;Up until now, checking if a collection was &lt;code&gt;null&lt;/code&gt; before using the subscript operator was verbose:&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="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="n"&gt;first&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;?&lt;/span&gt; &lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;items&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// null check to prevent runtime null errors&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Dart 2.9 introduces the &lt;code&gt;null&lt;/code&gt; aware operator &lt;code&gt;?[]&lt;/code&gt;, which makes this a lot easier:&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="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="n"&gt;first&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;?&lt;/span&gt; &lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="o"&gt;?[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;];&lt;/span&gt; 
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The late keyword
&lt;/h2&gt;

&lt;p&gt;Use the &lt;code&gt;late&lt;/code&gt; keyword to initialize a variable when it is &lt;strong&gt;first read&lt;/strong&gt;, rather than when it's &lt;strong&gt;created&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;A good example is when initializing variables in &lt;code&gt;initState()&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;class&lt;/span&gt; &lt;span class="nc"&gt;ExampleState&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="n"&gt;State&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;late&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;TextEditingController&lt;/span&gt; &lt;span class="n"&gt;textEditingController&lt;/span&gt;&lt;span class="o"&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;initState&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&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="o"&gt;();&lt;/span&gt;
    &lt;span class="n"&gt;textEditingController&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;TextEditingController&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Even better, &lt;code&gt;initState()&lt;/code&gt; can be removed altogether:&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;ExampleState&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="n"&gt;State&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// late - will be initialized when first used (in the build method)&lt;/span&gt;
  &lt;span class="n"&gt;late&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;textEditingController&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;TextEditingController&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It's common to use &lt;code&gt;late&lt;/code&gt; in combination with &lt;code&gt;final&lt;/code&gt;, to &lt;strong&gt;defer&lt;/strong&gt; the creation of &lt;strong&gt;read-only&lt;/strong&gt; variables to when they are first read.&lt;/p&gt;

&lt;p&gt;This is ideal when creating variables whose initializer does some heavy work:&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;late&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;taskResult&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;doHeavyComputation&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When used within a function body, &lt;code&gt;late&lt;/code&gt; and &lt;code&gt;final&lt;/code&gt; can be used 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="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;late&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

  &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// ok&lt;/span&gt;
  &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// The late final local variable is already definitely initialized&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Though I don't recomment using late variables this way. Because this style can result in non-obvious runtime errors. 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;class&lt;/span&gt; &lt;span class="nc"&gt;X&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;late&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

  &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="n"&gt;set1&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

  &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="n"&gt;set2&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;;&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="o"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;X&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;X&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
  &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;set1&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
  &lt;span class="n"&gt;print&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;x&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
  &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;set2&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// LateInitializationError: Field 'x' has already been initialized.&lt;/span&gt;
  &lt;span class="n"&gt;print&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;x&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By declaring a non-nullable &lt;code&gt;late&lt;/code&gt; variable, we &lt;strong&gt;promise&lt;/strong&gt; that it will be non-null at runtime, and Dart helps us with some compile-time guarantees.&lt;/p&gt;

&lt;p&gt;But I recommend to only use &lt;code&gt;late&lt;/code&gt; sparingly, and to always initialize &lt;code&gt;late&lt;/code&gt; variables when they are declared.&lt;/p&gt;

&lt;h2&gt;
  
  
  Static and global variables
&lt;/h2&gt;

&lt;p&gt;All global variables &lt;strong&gt;must now be initialized when they are declared&lt;/strong&gt; unless they are &lt;code&gt;late&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="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;global1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// ok&lt;/span&gt;

&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;global2&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// The non-nullable variable 'global2' must be initialized&lt;/span&gt;

&lt;span class="n"&gt;late&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;global3&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// ok&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The same applies to static class variables:&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;Constants&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// ok&lt;/span&gt;
  &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// The non-nullable variable 'y' must be initialized&lt;/span&gt;
  &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="n"&gt;late&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;z&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// ok&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But as I said before, I do not recommend using &lt;code&gt;late&lt;/code&gt; this way as it can lead to runtime errors.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Null Safety is a major change for the Dart language, and it has been introduced to help you write better and safer code.&lt;/p&gt;

&lt;p&gt;But at the end of the day, Null Safety is just a tool, and it is your job to use it correctly.&lt;/p&gt;

&lt;p&gt;Every time you declare a variable in Dart, think about whether it should be nullable or not. This may seem like extra work, but it will lead to better code and Dart can help you along the way.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;As of June 2020, Null Safety is in Tech Preview, and is not intended to be used in production code. Full Null Safety as a stable feature is planned before the end of the year (for the latest updates see &lt;a href="https://dart.dev/null-safety"&gt;dart.dev/null-safety&lt;/a&gt;).&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;If you can't wait, you can port existing projects to Null Safety and automate the process with this &lt;a href="https://pub.dev/packages/nnbd_migration"&gt;migration tool&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;p&gt;This article was mainly inspired by these sources:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://medium.com/dartlang/announcing-sound-null-safety-defd2216a6f3"&gt;Announcing sound null safety&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://stackoverflow.com/questions/60068435/what-is-null-safety-in-dart/60068436#60068436"&gt;What is Null Safety in Dart? | Stack Overflow&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://medium.com/dartlang/dart-nullability-syntax-decision-a-b-or-a-b-d827259e34a3"&gt;Dart nullability syntax decision: a?[b] or a?.[b]&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dart.dev/null-safety"&gt;Sound Null Safety | dart.dev&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Migration resources: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://pub.dev/packages/nnbd_migration"&gt;Null Safety Migration Tooling | pub.dev&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://stackoverflow.com/questions/62148950/how-to-migrate-dart-code-to-non-nullable-nnbd"&gt;How to migrate Dart code to Non-nullable (NNBD)? | Stack Overflow&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Happy coding!&lt;/p&gt;

</description>
      <category>dart</category>
    </item>
    <item>
      <title>23 Top Tips to Become a Better Software Engineer</title>
      <dc:creator>Andrea Bizzotto</dc:creator>
      <pubDate>Thu, 25 Jun 2020 20:46:20 +0000</pubDate>
      <link>https://dev.to/biz84/23-top-tips-to-become-a-better-software-engineer-5hga</link>
      <guid>https://dev.to/biz84/23-top-tips-to-become-a-better-software-engineer-5hga</guid>
      <description>&lt;p&gt;&lt;a href="https://codewithandrea.com/videos/2020-06-15-top-tips-software-engineers/"&gt;This article was originally published on my website.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://youtu.be/IxbkaJIjVsc"&gt;Also available on YouTube.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;One question people often ask me is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How can I become a Pro / Senior software engineer, and how long will it take?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And if I have to be honest, I don't think this is the right question to ask.&lt;/p&gt;

&lt;p&gt;I've been coding for over 15 years, and to this day there is &lt;em&gt;&lt;strong&gt;just so much stuff&lt;/strong&gt;&lt;/em&gt; that I still don't know.&lt;/p&gt;

&lt;p&gt;There isn't really a magical moment when you become a Pro. &lt;/p&gt;

&lt;p&gt;Rather, you should have the right mindset, and realize that &lt;strong&gt;programming is a long and winding journey&lt;/strong&gt;. It can have ups and downs, but also be very rewarding and enjoyable.&lt;/p&gt;

&lt;p&gt;So in this article I'm sharing 23 top tips that can help you become a better software developer.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Always be learning
&lt;/h2&gt;

&lt;p&gt;The Tech industry is very volatile and things change all the time. There are so many technologies to learn and so many languages to choose from.&lt;/p&gt;

&lt;p&gt;This can be quite intimidating. But if you have the right mindset, and you like learning new things, you can enjoy the journey without feeling overwhelmed.&lt;/p&gt;

&lt;p&gt;And of course, everyone learns differently. So find the method that works best for you, and get good at it.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Pick one language and stick to it
&lt;/h2&gt;

&lt;p&gt;If you try to learn too many things at once, you're more likely to lose your motivation and give up.&lt;/p&gt;

&lt;p&gt;Forget about the endless stream of articles and people telling you that you need to learn this new language or that new library.&lt;/p&gt;

&lt;p&gt;Instead pick just one that you're excited about, start with the basics and stick with it until you're comfortable with it.&lt;/p&gt;

&lt;p&gt;As you get started, it may be a good idea to read the documentation and follow some tutorials, to get a basic grasp of the language.&lt;/p&gt;

&lt;p&gt;But after that, there's no better way to learn a language than to build something with it.&lt;/p&gt;

&lt;p&gt;Only after you have a good understanding of the fundamentals, consider learning a new language to broaden your skills.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Build something
&lt;/h2&gt;

&lt;p&gt;Maybe there's an app or a website that you wanted to build for a long time.&lt;/p&gt;

&lt;p&gt;Make this a side project.&lt;/p&gt;

&lt;p&gt;If you can, set aside some time to work on it every day.&lt;/p&gt;

&lt;p&gt;Maybe you'll feel that you're not accomplishing much on any given day, but Rome wasn't built in a day.&lt;/p&gt;

&lt;p&gt;After a few weeks or months you'll see &lt;strong&gt;your&lt;/strong&gt; product coming to life, and this is extremely satisfying.&lt;/p&gt;

&lt;p&gt;Choose a project that challenges you, but is not too far above your skill level. As you build your confidence, you can go bigger and tackle more complex projects.&lt;/p&gt;

&lt;p&gt;In fact, you only improve when you &lt;strong&gt;keep challenging&lt;/strong&gt; yourself. Keep building &lt;strong&gt;new&lt;/strong&gt; and &lt;strong&gt;different&lt;/strong&gt; things.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Break out of tutorial hell
&lt;/h2&gt;

&lt;p&gt;If you are just starting to learn, it's very easy to fall in a trap where you do tutorial after tutorial after tutorial.&lt;/p&gt;

&lt;p&gt;Guess what? Once you get a job no-one is going to hold your hand, and there won't be a tutorial for every single task you need to get done.&lt;/p&gt;

&lt;p&gt;Try to break out of this cycle, and figure things out on your own.&lt;/p&gt;

&lt;p&gt;By solving problems yourself, your learning will improve considerably and you'll have a more concrete understanding of how things work.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Read the documentation
&lt;/h2&gt;

&lt;p&gt;This is the single best way of breaking out of tutorial hell.&lt;/p&gt;

&lt;p&gt;And the good news is that, documentation is just one click away. You can easily see the documentation for your SDK or libraries you use right from your editor.&lt;/p&gt;

&lt;p&gt;To be fair, not all documentation is created equal and some languages have it better than others.&lt;/p&gt;

&lt;p&gt;But knowing how to read it and use it, means that you no longer have to rely on tutorials.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Learn how to debug
&lt;/h2&gt;

&lt;p&gt;Coding is great but it can also be a frustrating experience.&lt;/p&gt;

&lt;p&gt;It's hard to know upfront every state that your code can be in (&lt;em&gt;though writing tests helps with that&lt;/em&gt;).&lt;/p&gt;

&lt;p&gt;Sometimes things won't work, and you'll find yourself stuck for hours without making progress.&lt;/p&gt;

&lt;p&gt;So what can you do when that happens?&lt;/p&gt;

&lt;p&gt;If you're getting some errors in your console, read them carefully as they may contain the information you need in order to solve your problem.&lt;/p&gt;

&lt;p&gt;Try to become familiar with the debugging tools in your code editor.&lt;/p&gt;

&lt;p&gt;Use print statements and breakpoints to step through your code and verify your assumptions, and learn more advanced debugging techniques too. These can save you a lot of time.&lt;/p&gt;

&lt;h2&gt;
  
  
  7. Get good at Googling
&lt;/h2&gt;

&lt;p&gt;This is an essential skill that programmers use all the time, even senior ones.&lt;/p&gt;

&lt;p&gt;So knowing how to find answers effectively can save you a lot of time.&lt;/p&gt;

&lt;p&gt;If you encounter an error, you can copy paste it into your favourite search engine, and &lt;strong&gt;carefully review&lt;/strong&gt; all the relevant answers.&lt;/p&gt;

&lt;p&gt;It may take you a bit of time to figure out how to do this effectively, but you'll get better at it over time.&lt;/p&gt;

&lt;h2&gt;
  
  
  8. Understand how the code ACTUALLY works
&lt;/h2&gt;

&lt;p&gt;We've all been there. We found some code on Stack Overflow, and added it to our project, hoping it might work.&lt;/p&gt;

&lt;p&gt;Don't &lt;em&gt;just&lt;/em&gt; stop there. Take the time to understand how the code &lt;strong&gt;actually&lt;/strong&gt; works. Make sure that it works under all possible cases, and adjust it to fit your project style and conventions.&lt;/p&gt;

&lt;p&gt;As a word of caution, code that you find on StackOverflow or other forums gets quickly out of date. See tip #5 about reading the documentation.&lt;/p&gt;

&lt;h2&gt;
  
  
  9. Reach out if you need help
&lt;/h2&gt;

&lt;p&gt;If you can't find the answer you need, don't let that discourage you.&lt;/p&gt;

&lt;p&gt;You can always post your question on StackOverflow. When you do this, choose a good title, and try to give enough context so that others can help you.&lt;/p&gt;

&lt;p&gt;Also, find out if your specific language or framework has a Slack or Discord channel, and join it.&lt;/p&gt;

&lt;p&gt;You may just find that there is an entire community of developers that are willing to help, as long as you're polite and ask nicely.&lt;/p&gt;

&lt;h2&gt;
  
  
  10. Learn how to write tests
&lt;/h2&gt;

&lt;p&gt;This will make you a better developer, and force you to think about all possible edge cases in your code - not just the happy path.&lt;/p&gt;

&lt;p&gt;It will also teach you how to write &lt;strong&gt;testable&lt;/strong&gt; code, and learn about important concepts like &lt;strong&gt;dependency injection&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;When you choose which tests to write, ask yourself:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;What would be the impact if this feature didn't work?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Then prioritize writing tests by impact:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a broken link for showing the terms &amp;amp; conditions in the setting page may not be a big deal.&lt;/li&gt;
&lt;li&gt;a purchase flow that fails and doesn't unlock core features in your app is a big deal.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Try to have good test coverage for business-critical code, and automate as many tests as possible.&lt;/p&gt;

&lt;h2&gt;
  
  
  11. Learn Git and how to use the Terminal
&lt;/h2&gt;

&lt;p&gt;No matter what area of programming you're in, you need at least some basic knowledge of Git and the command line - you'll be using these tools day in, day out.&lt;/p&gt;

&lt;p&gt;Try to learn about the more advanced features of Git as well. These will be very helpful when you work on projects with multiple collaborators.&lt;/p&gt;

&lt;p&gt;Also, become familiar with continuous integration systems and how to set them up.&lt;/p&gt;

&lt;h2&gt;
  
  
  12. Create value for your users and the business
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;The reason you're coding is that you're trying to solve a real, tangible problem that your users or customers have.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;So always try to focus on the users and business needs, and have the big picture in mind.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;That way you're more likely to add value to the product.&lt;/p&gt;

&lt;p&gt;One mistake that I often see other developers make, is to get stuck on one problem and go deeper and deeper into the rabbit hole.&lt;/p&gt;

&lt;p&gt;That's not a very effective use of time. &lt;/p&gt;

&lt;p&gt;So the next time this happens to you, set a time limit. Once the time is up, stop and take a break. Maybe the solution will come to you later in the shower. 🚿&lt;/p&gt;

&lt;h2&gt;
  
  
  13. Problem solving
&lt;/h2&gt;

&lt;p&gt;Customers/companies will pay you to solve their problems, not to know the syntax of language X.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Learn how to break problems into smaller ones that are easier to solve.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;To solve big problems, you need to think about the big picture, all the way from UX to system design. &lt;/p&gt;

&lt;p&gt;To design and build an entire product, and you'll need (at least some) knowledge of:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;UI/UX design&lt;/li&gt;
&lt;li&gt;data structures and algorithms&lt;/li&gt;
&lt;li&gt;design patterns and system architecture&lt;/li&gt;
&lt;li&gt;networking and databases&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Of course, if your role is more specialized you can focus on one specific area. &lt;/p&gt;

&lt;p&gt;But in any case, you'll need to &lt;strong&gt;choose the right tools for the job&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Problem solving is an abstract, broad skill that takes time to develop.&lt;/p&gt;

&lt;p&gt;My best advice here is to work on many different projects. As you do this, you'll start seeing what works and what doesn't, and draw on your previous experience.&lt;/p&gt;

&lt;p&gt;Quoting Dan Abramov &lt;a href="https://twitter.com/dan_abramov/status/1260762854631800835"&gt;on Twitter&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;The reason an experienced engineer moves so much faster than a beginner is because they opened most of the “doors” they encounter in code thousands of times before. They stop to think, but so much is done purely by recall. This is why you need to practice, practice, practice - Dan Abramov&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  14. Focus
&lt;/h2&gt;

&lt;p&gt;To be good at coding you need to focus and work without interruptions for a long enough amount of time.&lt;/p&gt;

&lt;p&gt;When you're coding, try to avoid all distractions. That includes social media, emails, your cat, as well as Slack and other ways that your co-workers may reach you. &lt;/p&gt;

&lt;p&gt;If needed, set specific times for this. Make it clear when you're in the coding zone, and others will respect that.&lt;/p&gt;

&lt;h2&gt;
  
  
  15. Be Organized &amp;amp; Plan Ahead
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;If you fail to plan, you are planning to fail - Benjamin Franklin&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Whether you're working on just one project, or have many things at hand and you need to keep on top of them, try to be organized.&lt;/p&gt;

&lt;p&gt;One of my habits is to keep a daily TODO list of all the things that I plan to do.&lt;/p&gt;

&lt;p&gt;And I find it very satisfying to tick off all the tasks at the end of the day (though sometimes I move them to the next day 😅).&lt;/p&gt;

&lt;p&gt;Beyond that I also have longer term goals and plans, so that I can keep track of my progress and focus on what matters.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;To organize all my work I use &lt;a href="https://www.notion.so/"&gt;Notion&lt;/a&gt;, which has become my favourite productivity tool (&lt;em&gt;disclosure: I'm not sponsoring Notion - I just really like it&lt;/em&gt;).&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  16. Learn to read other people's code
&lt;/h2&gt;

&lt;p&gt;Chances are that throughout your career you'll spend more time reading code, than writing it.&lt;/p&gt;

&lt;p&gt;Getting good at reading code will help you to understand many different codebases. &lt;/p&gt;

&lt;p&gt;Where can you do this?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Read the documentation and source code for libraries or frameworks you already use.&lt;/li&gt;
&lt;li&gt;Find some popular open source projects on GitHub. Once you find a good project, check out the code, and open it in your editor. Then try to run it and understand how it works.&lt;/li&gt;
&lt;li&gt;If you work in a team, do code reviews.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As you do this, try to think about how the code could be improved.&lt;/p&gt;

&lt;p&gt;Doing this will make you more aware about style and conventions, so that you can improve the way you write &lt;em&gt;your&lt;/em&gt; code.&lt;/p&gt;

&lt;p&gt;Your future self will thank you for this. 😉&lt;/p&gt;

&lt;h2&gt;
  
  
  17. Get involved in Open Source
&lt;/h2&gt;

&lt;p&gt;By contributing to existing open-source projects, you can improve your code-reading skills, and get valuable feedback on your own code.&lt;/p&gt;

&lt;p&gt;To get started, you can join the &lt;a href="https://github.com/open-source"&gt;GitHub open source community&lt;/a&gt;, which contains &lt;a href="https://opensource.guide/"&gt;many useful resources&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;By writing open source code, you can &lt;strong&gt;stop re-inventing the wheel&lt;/strong&gt; and &lt;strong&gt;carry over your best code&lt;/strong&gt; across projects. And if your project is useful enough, &lt;a href="https://krausefx.com/blog/scaling-open-source-communities"&gt;it can have a big impact&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Doing this is also great for your CV&lt;/strong&gt;. A good GitHub profile shows tangible proof of your skills and coding style, and increases your chances of getting a job.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;On a personal note, &lt;a href="https://github.com/bizz84"&gt;my GitHub profile&lt;/a&gt; alone allowed me to stand out in job interviews and negotiate great offers time and again, before I even became an instructor and a Flutter GDE.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  18. Stay up to date
&lt;/h2&gt;

&lt;p&gt;You don't need to read every single article and watch every YouTube video out there.&lt;/p&gt;

&lt;p&gt;And you shouldn't be following tutorials &lt;strong&gt;only&lt;/strong&gt;. Trying things out on your own is more important.&lt;/p&gt;

&lt;p&gt;But you should try to find the right resources to fast-track your learning, so that you don't have to figure out &lt;strong&gt;everything&lt;/strong&gt; by yourself.&lt;/p&gt;

&lt;p&gt;Try to find a list of experts who regularly share quality content, and subscribe to their feeds (&lt;em&gt;if you're into Flutter, &lt;a href="https://blog.codemagic.io/top-flutter-developers-to-follow-on-twitter/"&gt;here's a good list&lt;/a&gt;&lt;/em&gt;).&lt;/p&gt;

&lt;p&gt;I find this is a great way to stay up to date and learn about new things.&lt;/p&gt;

&lt;h2&gt;
  
  
  19. Learn basic design
&lt;/h2&gt;

&lt;p&gt;You don't need to become a professional designer.&lt;/p&gt;

&lt;p&gt;But you should understand the basic principles of design, and become familiar with at least one design tool (here's a few: &lt;a href="https://www.sketch.com/"&gt;Sketch&lt;/a&gt;, &lt;a href="https://www.figma.com/"&gt;Figma&lt;/a&gt;, &lt;a href="https://www.adobe.com/products/xd.html"&gt;Adobe XD&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;This way you can make your own work look good, especially if potential employers or clients will see this.&lt;/p&gt;

&lt;p&gt;But it also expands your sphere of knowledge, and helps you &lt;strong&gt;think about problems in terms of UX and not just code&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  20. Learn to communicate
&lt;/h2&gt;

&lt;p&gt;This one is super important. &lt;strong&gt;I don't think you can be a great developer if you can't communicate well&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;You should be able to explain things in plain English (even if it's not your first language), so that non-technical people in your team can understand you.&lt;/p&gt;

&lt;p&gt;Beyond that, always communicate clearly what you're working on, what problems you're facing, and make sure you do what you say you'll do.&lt;/p&gt;

&lt;p&gt;If you work remotely, take 5 minutes every day to share your updates. &lt;em&gt;I always do this, and my clients really appreciate it.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;All this builds trust. Being &lt;strong&gt;reliable&lt;/strong&gt; and &lt;strong&gt;trustworthy&lt;/strong&gt; can be your single best asset, and is absolutely critical if you are a freelancer.&lt;/p&gt;

&lt;h2&gt;
  
  
  21. Do your best work
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Your work is your brand. Your brand is what sets you apart. So always aim to deliver the best work you can.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you can impress the people you work with, they're more likely to recommend you when you're looking for a new job.&lt;/p&gt;

&lt;p&gt;And when you publish your own work, whether it's a GitHub project, your portfolio, an article or YouTube video, that is for everyone to see. So make it look great.&lt;/p&gt;

&lt;h2&gt;
  
  
  22. Share your knowledge
&lt;/h2&gt;

&lt;p&gt;When you learn something useful, blog about it. Explaining things in writing can improve your knowledge on a certain topic.&lt;/p&gt;

&lt;p&gt;Practice making your writing more &lt;strong&gt;clear&lt;/strong&gt; and &lt;strong&gt;concise&lt;/strong&gt;. This is a valuable skill in itself - especially if you work remotely.&lt;/p&gt;

&lt;p&gt;Keep writing, and you'll build a trove of knowledge that you can share with others, and come back to when you need.&lt;/p&gt;

&lt;p&gt;This will also boost your profile and CV, and help you engage with your community. &lt;/p&gt;

&lt;h2&gt;
  
  
  23. Take care of yourself
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Life is short and things can go wrong faster than you may think.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;So drink plenty of water. Do exercise. Eat &amp;amp; sleep well. Don't work too much. &lt;/p&gt;

&lt;p&gt;Look after yourself and others close to you.&lt;/p&gt;

&lt;h2&gt;
  
  
  Feeling overwhelmed?
&lt;/h2&gt;

&lt;p&gt;We've covered a lot of stuff. If all this feels a bit overwhelming, don't worry.&lt;/p&gt;

&lt;p&gt;Take things step by step. As long as you're learning and continuing to grow, then you're on the right track.&lt;/p&gt;

&lt;h2&gt;
  
  
  Still not sure where to start (or where to go next)?
&lt;/h2&gt;

&lt;p&gt;Check out this &lt;a href="https://roadmap.sh/"&gt;Developer Roadmaps&lt;/a&gt; website. It includes learning roadmaps for frontend, backend developers and more. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;UPDATE 2020-06-18: A new Flutter Developer Roadmap 2020 was published on GitHub. &lt;a href="https://github.com/DroidsOnRoids/flutter-roadmap"&gt;Check it out here&lt;/a&gt;!&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;When I started writing this article, I had four items on my list. I ended up with 23, and there are still many more that I have left out.&lt;/p&gt;

&lt;p&gt;What are your top tips? Let me know in the comments.&lt;/p&gt;

&lt;p&gt;Thanks for reading!&lt;/p&gt;

</description>
      <category>career</category>
      <category>productivity</category>
    </item>
    <item>
      <title> How to Create Dart Packages for Your Flutter Apps</title>
      <dc:creator>Andrea Bizzotto</dc:creator>
      <pubDate>Mon, 01 Jun 2020 06:52:16 +0000</pubDate>
      <link>https://dev.to/biz84/how-to-create-dart-packages-for-your-flutter-apps-4ehm</link>
      <guid>https://dev.to/biz84/how-to-create-dart-packages-for-your-flutter-apps-4ehm</guid>
      <description>&lt;p&gt;&lt;a href="https://codewithandrea.com/videos/2020-06-01-how-to-create-dart-packages-flutter-apps/" rel="noopener noreferrer"&gt;This article was originally published on my website.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://youtu.be/ZABb7PTkT58" rel="noopener noreferrer"&gt;Watch the Video Tutorial on YouTube.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this tutorial I'll show you how to create Dart packages for your Flutter apps, so that you can &lt;strong&gt;improve&lt;/strong&gt; and &lt;strong&gt;reuse&lt;/strong&gt; your code.&lt;/p&gt;

&lt;p&gt;Why is this important?&lt;/p&gt;

&lt;p&gt;With large applications, it is challenging to keep folders organized, and minimise inter-dependencies between files and different parts of the app.&lt;/p&gt;

&lt;p&gt;Dart packages solve this problem by making apps more &lt;strong&gt;modular&lt;/strong&gt; and dependencies more &lt;strong&gt;explicit&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;So if you have a single large application, or multiple apps that need to share some functionality, extracting reusable code into packages is the way forward.&lt;/p&gt;

&lt;h2&gt;
  
  
  How this tutorial is organized
&lt;/h2&gt;

&lt;p&gt;We will start with a step-by-step guide and convert a sample BMI calculator application to use &lt;strong&gt;internal&lt;/strong&gt; packages &lt;strong&gt;within the same project&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Then, we will talk about:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Dealing with existing, large apps&lt;/li&gt;
&lt;li&gt;Reusing packages across multiple apps&lt;/li&gt;
&lt;li&gt;Local vs remove (git) packages&lt;/li&gt;
&lt;li&gt;Versioning packages and the humble changelog&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's get started!&lt;/p&gt;

&lt;h2&gt;
  
  
  Example: BMI calculator
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;To follow along each step, you can download the &lt;a href="https://github.com/bizz84/bmi_calculator_app_flutter" rel="noopener noreferrer"&gt;starter project here&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Suppose we have a single page BMI calculator app, composed of these four files:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;lib/
    bmi_calculation_page.dart
    bmi_calculator.dart
    bmi_formatter.dart
    main.dart
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The most interesting functionality is in &lt;code&gt;bmi_calculator.dart&lt;/code&gt; and &lt;code&gt;bmi_formatter.dart&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="c1"&gt;// bmi_calculator.dart&lt;/span&gt;
&lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="nf"&gt;calculateBMI&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;weight&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;height&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;weight&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;height&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;height&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;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="c1"&gt;// bmi_formatter.dart&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="s"&gt;'package:intl/intl.dart'&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="nf"&gt;formattedBMI&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;bmi&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;formatter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;NumberFormat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&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;formatter&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bmi&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;The UI is built with a single &lt;code&gt;BMICalculationPage&lt;/code&gt; widget class. This shows two input text fields for the weight and height, and one output text field for the BMI (&lt;a href="https://github.com/bizz84/bmi_calculator_app_flutter" rel="noopener noreferrer"&gt;full source here&lt;/a&gt;):&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Ffh17bqumeum43w8yl07v.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Ffh17bqumeum43w8yl07v.png" alt="BMI calculator screenshot"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This app is simple enough that we can keep all files inside &lt;code&gt;lib&lt;/code&gt;. But how can we reuse the BMI calculation and formatting logic across other projects?&lt;/p&gt;

&lt;p&gt;We could copy-paste &lt;code&gt;bmi_calculator.dart&lt;/code&gt; and &lt;code&gt;bmi_formatter.dart&lt;/code&gt; on each new project.&lt;/p&gt;

&lt;p&gt;But copy pasting is rarely a good thing. If we want to change the number of decimal places in the formatter code, we have to do it in each project. Not very DRY. 🌵&lt;/p&gt;

&lt;h3&gt;
  
  
  Creating a new package
&lt;/h3&gt;

&lt;p&gt;A better approach is to create a new &lt;strong&gt;package&lt;/strong&gt; for all the shared code.&lt;/p&gt;

&lt;p&gt;In doing this, we should consider the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;By convention, all packages should go inside a &lt;code&gt;packages&lt;/code&gt; folder.&lt;/li&gt;
&lt;li&gt;When starting from a single application, it's simpler to add the new package(s) inside the &lt;strong&gt;same&lt;/strong&gt; git repo.&lt;/li&gt;
&lt;li&gt;If we need to share packages across multiple projects, we can move them to a new git repo (more on this below).&lt;/li&gt;
&lt;li&gt;We can &lt;strong&gt;keep multiple packages inside a single repository&lt;/strong&gt;. The &lt;a href="https://github.com/FirebaseExtended/flutterfire" rel="noopener noreferrer"&gt;FlutterFire&lt;/a&gt; &lt;strong&gt;monorepo&lt;/strong&gt; is a good example of this, and I recommend we do the same for simplicity.&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;For this example, we'll add a new package and keep it inside the same git repo.&lt;/p&gt;

&lt;p&gt;From the root of your project, we can run this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mkdir packages
cd packages
flutter create --template=package bmi
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will create a new Flutter package in &lt;code&gt;packages/bmi&lt;/code&gt;, but the &lt;code&gt;main.dart&lt;/code&gt; file with the usual &lt;code&gt;runApp(MyApp())&lt;/code&gt; code is missing. Instead, we have a &lt;code&gt;bmi.dart&lt;/code&gt; file with some default boilerplate:&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;library&lt;/span&gt; &lt;span class="n"&gt;bmi&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;/// A Calculator.&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Calculator&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;/// Returns [value] plus 1.&lt;/span&gt;
  &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;addOne&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;value&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;value&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&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;As we don't need the &lt;code&gt;Calculator&lt;/code&gt; class, we can replace it with the BMI calculation and formatting code from the main app.&lt;/p&gt;

&lt;p&gt;The simplest way to do this is to add all the code from &lt;code&gt;lib/bmi_calculator.dart&lt;/code&gt; and &lt;code&gt;lib/bmi_formatter.dart&lt;/code&gt; to &lt;code&gt;packages/bmi/lib/bmi.dart&lt;/code&gt; (&lt;em&gt;we will see later on how to have multiple files inside a package&lt;/em&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="c1"&gt;// bmi.dart&lt;/span&gt;
&lt;span class="kn"&gt;library&lt;/span&gt; &lt;span class="n"&gt;bmi&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="s"&gt;'package:intl/intl.dart'&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="nf"&gt;calculateBMI&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;weight&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;height&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;weight&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;height&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;height&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="nf"&gt;formattedBMI&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;bmi&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;formatter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;NumberFormat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&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;formatter&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bmi&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;Note that this code depends on &lt;code&gt;intl&lt;/code&gt;, so we need to add this to the &lt;code&gt;pubspec.yaml&lt;/code&gt; file &lt;strong&gt;of our package&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;dependencies&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;flutter&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;sdk&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;flutter&lt;/span&gt;
  &lt;span class="na"&gt;intl&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;^0.16.1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Using the new package
&lt;/h3&gt;

&lt;p&gt;Now that we have a &lt;code&gt;bmi&lt;/code&gt; package, we need to add it as a dependency to &lt;strong&gt;our app&lt;/strong&gt;'s &lt;code&gt;pubspec.yaml&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;dependencies&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;flutter&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;sdk&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;flutter&lt;/span&gt;
  &lt;span class="c1"&gt;# Used by bmi_calculation_page.dart&lt;/span&gt;
  &lt;span class="na"&gt;flutter_hooks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;^0.9.0&lt;/span&gt;
  &lt;span class="c1"&gt;# we no longer need to import intl explicitly, as bmi already depends on it&lt;/span&gt;
  &lt;span class="na"&gt;bmi&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;packages/bmi&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here we use a &lt;code&gt;path&lt;/code&gt; argument to tell Flutter &lt;strong&gt;where&lt;/strong&gt; to find our new package. This works &lt;strong&gt;as long as the package lives in the same repo&lt;/strong&gt;.&lt;/p&gt;




&lt;p&gt;After running &lt;code&gt;flutter pub get&lt;/code&gt; (from the root of the project), the package will be installed and we can use it, just like we would do with any other Dart package.&lt;/p&gt;

&lt;p&gt;So we can update the imports in our &lt;code&gt;bmi_calculator_page.dart&lt;/code&gt; from 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:bmi_calculator_app_flutter/bmi_calculator.dart'&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="s"&gt;'package:bmi_calculator_app_flutter/bmi_formatter.dart'&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;to 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:bmi/bmi.dart'&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And viola! Our code works and we can now remove &lt;code&gt;bmi_calculator.dart&lt;/code&gt; and &lt;code&gt;bmi_formatter.dart&lt;/code&gt; from the main app project. 🏁&lt;/p&gt;

&lt;p&gt;In summary, to extract existing code to a separate package we have to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;create a new package and move our code inside it.&lt;/li&gt;
&lt;li&gt;add any dependencies to the &lt;code&gt;pubspec.yaml&lt;/code&gt; file &lt;strong&gt;for the package&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;add the new package as a dependency to &lt;code&gt;pubspec.yaml&lt;/code&gt; &lt;strong&gt;for our application&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;replace the old imports with the new package where needed.&lt;/li&gt;
&lt;li&gt;delete all the old files.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Bonus: Adding multiple files to a package with &lt;code&gt;part&lt;/code&gt; and &lt;code&gt;part of&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;This example is simple enough that we can keep the BMI calculation and formatting code in &lt;code&gt;bmi.dart&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;But as our package grows, we should split the code into multiple files.&lt;/p&gt;

&lt;p&gt;So rather than keeping everything in one file 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="c1"&gt;// bmi.dart&lt;/span&gt;
&lt;span class="kn"&gt;library&lt;/span&gt; &lt;span class="n"&gt;bmi&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="s"&gt;'package:intl/intl.dart'&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="nf"&gt;calculateBMI&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;weight&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;height&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;weight&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;height&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;height&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="nf"&gt;formattedBMI&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;bmi&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;formatter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;NumberFormat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&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;formatter&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bmi&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;We can move the &lt;code&gt;calculateBMI&lt;/code&gt; and &lt;code&gt;formattedBMI&lt;/code&gt; methods in separate files, just like we had them at the beginning:&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;// bmi_calculator.dart&lt;/span&gt;
&lt;span class="kn"&gt;part of&lt;/span&gt; &lt;span class="n"&gt;bmi&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="nf"&gt;calculateBMI&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;weight&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;height&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;weight&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;height&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;height&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;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="c1"&gt;// bmi_formatter.dart&lt;/span&gt;
&lt;span class="kn"&gt;part of&lt;/span&gt; &lt;span class="n"&gt;bmi&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="nf"&gt;formattedBMI&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;bmi&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;formatter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;NumberFormat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&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;formatter&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bmi&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, we can update &lt;code&gt;bmi.dart&lt;/code&gt; to specify its &lt;code&gt;part&lt;/code&gt;s:&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;// bmi.dart&lt;/span&gt;
&lt;span class="kn"&gt;library&lt;/span&gt; &lt;span class="n"&gt;bmi&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="s"&gt;'package:intl/intl.dart'&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;part&lt;/span&gt; &lt;span class="s"&gt;'bmi_calculator.dart'&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;part&lt;/span&gt; &lt;span class="s"&gt;'bmi_formatter.dart'&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A few notes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Files declared with &lt;code&gt;part of&lt;/code&gt; should &lt;strong&gt;not&lt;/strong&gt; contain any &lt;code&gt;import&lt;/code&gt;s, or we'll get compile errors.&lt;/li&gt;
&lt;li&gt;Instead, all &lt;code&gt;import&lt;/code&gt;s should remain in the main file that specifies all the &lt;code&gt;part&lt;/code&gt;s.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In essence, we're saying that &lt;code&gt;bmi_calculator.dart&lt;/code&gt; and &lt;code&gt;bmi_formatter.dart&lt;/code&gt; are &lt;code&gt;part of&lt;/code&gt; &lt;code&gt;bmi.dart&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;When we import &lt;code&gt;bmi.dart&lt;/code&gt; in the main app, all &lt;strong&gt;public&lt;/strong&gt; symbols defined in all its parts will be visible.&lt;/p&gt;

&lt;p&gt;In other words, our main app just needs to &lt;code&gt;import 'package:bmi/bmi.dart';&lt;/code&gt;, and have access to all the methods declared in all its parts.&lt;/p&gt;

&lt;p&gt;Job done! You can find the finished project for this tutorial &lt;a href="https://github.com/bizz84/bmi_calculator_app_flutter" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: Using &lt;code&gt;part&lt;/code&gt; and &lt;code&gt;part of&lt;/code&gt; works well if you have &lt;strong&gt;just a few files&lt;/strong&gt; in the same folder. One library that uses this extensively is &lt;a href="https://pub.dev/packages/flutter_bloc" rel="noopener noreferrer"&gt;flutter_bloc&lt;/a&gt;, where it's common to define &lt;strong&gt;state&lt;/strong&gt;, &lt;strong&gt;event&lt;/strong&gt; and &lt;strong&gt;bloc&lt;/strong&gt; classes together.&lt;/p&gt;

&lt;p&gt;For more complex apps it's advisable (and recommended by the Dart team) to &lt;strong&gt;export&lt;/strong&gt; library files instead. See &lt;a href="https://dart.dev/guides/libraries/create-library-packages" rel="noopener noreferrer"&gt;this official guide on creating packages&lt;/a&gt; for more details.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Top tip&lt;/strong&gt;: moving code into packages is a great opportunity to move existing tests, or write new ones.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Creating a package for a simple app is easy enough, but how do we do this when we have complex apps?&lt;/p&gt;

&lt;h2&gt;
  
  
  Dealing with existing, large apps
&lt;/h2&gt;

&lt;p&gt;For more complex apps, we can &lt;strong&gt;incrementally&lt;/strong&gt; move code into self-contained packages.&lt;/p&gt;

&lt;p&gt;This forces us to think harder about the dependencies between packages.&lt;/p&gt;

&lt;p&gt;But if there are already a lot of inter-dependencies, how do we get started?&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;bottom-up&lt;/strong&gt; approach is most effective. Consider this example:&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;// lib/a.dart&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="s"&gt;'b.dart'&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="s"&gt;'c.dart'&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// lib/b.dart&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="s"&gt;'c.dart'&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// lib/d.dart&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="s"&gt;'a.dart'&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="s"&gt;'c.dart'&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// lib/c.dart&lt;/span&gt;
&lt;span class="c1"&gt;// no imports&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As we can see, &lt;code&gt;c.dart&lt;/code&gt; doesn't depend on any files.&lt;/p&gt;

&lt;p&gt;So moving &lt;code&gt;c.dart&lt;/code&gt; into a &lt;code&gt;c&lt;/code&gt; package would be a good first step.&lt;/p&gt;

&lt;p&gt;Then, we could move &lt;code&gt;b.dart&lt;/code&gt; into a separate &lt;code&gt;b&lt;/code&gt; package, making sure to add &lt;code&gt;c&lt;/code&gt; as a dependency:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# packages/b/pubspec.yaml&lt;/span&gt;
&lt;span class="na"&gt;dependencies&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;flutter&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;sdk&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;flutter&lt;/span&gt;
  &lt;span class="na"&gt;c&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;packages/c&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And we can repeat this process until all dependencies are taken care of.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;It's still our job to decide how many packages to create, and what goes in each one.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Reusing packages across multiple apps
&lt;/h2&gt;

&lt;p&gt;Up until now we've seen how to create new packages within the same project.&lt;/p&gt;

&lt;p&gt;If we want to reuse packages across multiple projects, we can move them to a &lt;strong&gt;common&lt;/strong&gt; shared repository.&lt;/p&gt;

&lt;p&gt;Using the BMI calculator example, we could update the &lt;code&gt;pubspec.yaml&lt;/code&gt; file to point to the new repository:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;dependencies&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="s"&gt;...&lt;/span&gt;
  &lt;span class="s"&gt;bmi&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;git&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;https://github.com/your-username/bmi&lt;/span&gt;
      &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;packages/bmi&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I followed this approach when refactoring my &lt;a href="https://github.com/bizz84/starter_architecture_flutter_firebase" rel="noopener noreferrer"&gt;starter architecture project&lt;/a&gt;, and ended up with 6 new packages that I now reuse in other projects.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;To learn more about to the package dependencies syntax, &lt;a href="https://dart.dev/tools/pub/dependencies" rel="noopener noreferrer"&gt;read this page&lt;/a&gt; on the Dart documentation.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Local vs remove (git) packages
&lt;/h2&gt;

&lt;p&gt;Dart packages make our code cleaner and increase code reuse, but do they slow us down?&lt;/p&gt;

&lt;p&gt;As long as we specify dependencies with &lt;code&gt;path&lt;/code&gt; in our &lt;code&gt;pubspec.yaml&lt;/code&gt; file, we can edit, commit and push all our code (main app &lt;strong&gt;and&lt;/strong&gt; packages) just as we did before.&lt;/p&gt;

&lt;p&gt;But if we move our packages to a separate repo, getting the latest code for our packages becomes more difficult:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;dependencies&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="s"&gt;...&lt;/span&gt;
  &lt;span class="s"&gt;bmi&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;git&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;https://github.com/your-username/bmi&lt;/span&gt;
      &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;packages/bmi&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's because &lt;code&gt;pub&lt;/code&gt; will &lt;strong&gt;cache&lt;/strong&gt; packages when we use &lt;code&gt;git&lt;/code&gt; as a source. Running &lt;code&gt;flutter pub get&lt;/code&gt; will keep the old cached version, even if we have pushed changes to the package.&lt;/p&gt;

&lt;p&gt;As a workaround we can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;comment out our package&lt;/li&gt;
&lt;li&gt;run &lt;code&gt;flutter pub get&lt;/code&gt; (to delete it from cache)&lt;/li&gt;
&lt;li&gt;uncomment the package&lt;/li&gt;
&lt;li&gt;run &lt;code&gt;flutter pub get&lt;/code&gt; again (to get the latest changes)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Repeating these steps every time we make a change is not fun. 🤔&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Bottom line: we get the fastest turnaround time by keeping all our code (apps and packages) &lt;strong&gt;in the same git repo&lt;/strong&gt;. That way we can specify package dependencies with &lt;code&gt;path&lt;/code&gt; and always use the latest code.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Versioning packages
&lt;/h2&gt;

&lt;p&gt;When we import packages from &lt;a href="https://pub.dev/" rel="noopener noreferrer"&gt;&lt;code&gt;pub.dev&lt;/code&gt;&lt;/a&gt;, we normally specify which &lt;strong&gt;version&lt;/strong&gt; we want to use.&lt;/p&gt;

&lt;p&gt;Each version corresponds to a &lt;strong&gt;release&lt;/strong&gt;, and we can preview the &lt;strong&gt;changelog&lt;/strong&gt; to see what changes across releases (example changelog from &lt;a href="https://pub.dev/packages/provider#-changelog-tab-" rel="noopener noreferrer"&gt;Provider&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;This makes it a lot easier to see what changed and when, and can help pinpoint bugs/regressions to a specific release.&lt;/p&gt;

&lt;p&gt;As you develop your own packages, I encourage you to also have a changelog. And don't forget to &lt;strong&gt;update the package version&lt;/strong&gt;, which lives at the top of the &lt;code&gt;pubspec.yaml&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;name: bmi
description: Utility functions to calculate the BMI.
version: 0.0.1
author:
homepage:
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is a good and useful habit if other devs will use your code, or you plan to publish your package on &lt;a href="https://pub.dev" rel="noopener noreferrer"&gt;&lt;code&gt;pub.dev&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Challenge: Refactor your apps
&lt;/h2&gt;

&lt;p&gt;Time to put things in practice with a challenge.&lt;/p&gt;

&lt;p&gt;Try extracting some code from one of your Flutter projects, and move it to one of more packages.&lt;/p&gt;

&lt;p&gt;And use this as an opportunity to think about dependencies in your own projects.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Dart packages are a good way to scale up projects, whether you work for yourself or as part of a big organization.&lt;/p&gt;

&lt;p&gt;They make code more modular and reusable, and with clearly defined dependencies.&lt;/p&gt;

&lt;p&gt;They also make it easier to &lt;strong&gt;split code ownership&lt;/strong&gt; with other collaborators.&lt;/p&gt;

&lt;p&gt;You should consider using them, whether you're working on a single large app, or many separate apps.&lt;/p&gt;

&lt;p&gt;After all, there's a reason we have an entire package ecosystem on &lt;a href="https://pub.dev" rel="noopener noreferrer"&gt;pub.dev&lt;/a&gt;. 😎&lt;/p&gt;

&lt;p&gt;Happy coding!&lt;/p&gt;

</description>
      <category>flutter</category>
      <category>dart</category>
    </item>
    <item>
      <title> Flutter REST API Crash Course Launch: Build a Coronavirus Tracking App</title>
      <dc:creator>Andrea Bizzotto</dc:creator>
      <pubDate>Mon, 02 Mar 2020 09:03:55 +0000</pubDate>
      <link>https://dev.to/biz84/flutter-rest-api-crash-course-launch-build-a-coronavirus-tracking-app-33i2</link>
      <guid>https://dev.to/biz84/flutter-rest-api-crash-course-launch-build-a-coronavirus-tracking-app-33i2</guid>
      <description>&lt;p&gt;&lt;a href="https://codewithandrea.com/videos/flutter-rest-api-crash-course-launch/"&gt;This article was originally published on my website.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://youtu.be/-5AgEisRQ5Y"&gt;Watch Video Tutorial on YouTube.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Today I'm launching a &lt;a href="https://courses.codewithandrea.com/"&gt;new crash course&lt;/a&gt;, where you will learn how to use REST APIs with Dart and Flutter.&lt;/p&gt;

&lt;p&gt;I created this course because REST APIs are used everywhere in today's web.&lt;/p&gt;

&lt;p&gt;And if you master the basics of the Dart &lt;a href="https://pub.dev/packages/http"&gt;http library&lt;/a&gt;, you can write Flutter apps that can tap into thousands of web APIs.&lt;/p&gt;

&lt;p&gt;So in this crash course we will build a simple but completely functional Coronavirus Tracker Application in Flutter.&lt;/p&gt;

&lt;p&gt;This application is just a simple dashboard that shows all the cases of Coronavirus worldwide.&lt;/p&gt;

&lt;p&gt;We will use the &lt;a href="https://apimarket.nubentos.com/store/apis/info?name=API-nCoV2019&amp;amp;version=1.0.0&amp;amp;tenant=nubentos.com"&gt;nCoV 2019 REST API&lt;/a&gt; to fetch the data. This is a free API that is relatively simple to use. But from a technical point of view, it will give us plenty of things to learn about.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's in this course
&lt;/h2&gt;

&lt;p&gt;Here's a list of topics that are covered in this crash course:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Short introduction to REST&lt;/strong&gt;: what it is and how it works&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Overview of the nCoV 2019 health API&lt;/strong&gt;. This is used to fetch statistics about the Coronavirus outbreak around the world.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Api keys &amp;amp; access tokens&lt;/strong&gt;: what they are and how to use them&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;REST Client&lt;/strong&gt;: a VSCode extension that you can use to send HTTP requests and view the response directly in VS Code&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Design a REST API service in Dart&lt;/strong&gt;: we will use the &lt;code&gt;http&lt;/code&gt; package and learn how to make requests&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Parsing JSON&lt;/strong&gt;, as needed when handling responses from the REST API&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Build a single-page UI&lt;/strong&gt;, using the API service that we created&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Combine multiple API requests&lt;/strong&gt; into a single response by using futures&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;How to use a RefreshIndicator&lt;/strong&gt; to get updated data from the API&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Error handling&lt;/strong&gt;: a very important topic when designing robust applications&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Shared preferences&lt;/strong&gt;: we will use this to cache API responses, so that the data is saved on device for offline use&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;This course is all about mastering the basics&lt;/strong&gt;. While we will only build a single page application, you will get all the knowledge you need to work with REST APIs in Dart, and use them to build slick-looking UIs in Flutter.&lt;/p&gt;

&lt;p&gt;Not only that, but we will talk about app architecture as well. Architecture is a very important topic, so we will build this app following best practices.&lt;/p&gt;

&lt;p&gt;And I'm confident that by the end of this course, you will be able to build Flutter apps that connect with any other REST API that you want to use.&lt;/p&gt;

&lt;h2&gt;
  
  
  Course organization
&lt;/h2&gt;

&lt;p&gt;This course will be divided into separate videos, and follow the topics in the order that I have described.&lt;br&gt;
You will have access to the full source code for each lesson, &lt;a href="https://github.com/bizz84/coronavirus_rest_api_flutter_course"&gt;right here on GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Familiarity with the Dart Language. If you're new to Dart, check out my &lt;a href="https://www.youtube.com/playlist?list=PLNnAcB93JKV_R1aZc7ZbQRsiEyeDLUpE-"&gt;Dart Introduction&lt;/a&gt; on YouTube.&lt;/li&gt;
&lt;li&gt;Have Flutter installed on your system.&lt;/li&gt;
&lt;li&gt;Visual Studio Code or Android Studio, configured for Flutter development.&lt;/li&gt;
&lt;li&gt;Some prior knowledge of the most common Flutter widgets, and the difference between stateful and stateless widgets.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Basics aside, this course is for you if you want to learn how to use REST APIs and build maintainable Flutter apps.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where to find this crash course
&lt;/h2&gt;

&lt;p&gt;Part of this course will be available for free on YouTube.&lt;br&gt;
To get the full content, you have to buy the course on Teachable.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Included for free&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Short introduction to REST&lt;/li&gt;
&lt;li&gt;Overview of the nCoV 2019 health API&lt;/li&gt;
&lt;li&gt;Api keys &amp;amp; access tokens&lt;/li&gt;
&lt;li&gt;REST Client&lt;/li&gt;
&lt;li&gt;Design a REST API service in Dart&lt;/li&gt;
&lt;li&gt;Parsing JSON&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Included in the paid course&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;All of the above, plus:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Build a single-page UI&lt;/li&gt;
&lt;li&gt;Combine multiple API requests with Futures&lt;/li&gt;
&lt;li&gt;How to use a RefreshIndicator&lt;/li&gt;
&lt;li&gt;Error handling&lt;/li&gt;
&lt;li&gt;Shared preferences and caching&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The paid course comes with &lt;strong&gt;premium support&lt;/strong&gt;. I will aim to answer all questions within 24 hours.&lt;/p&gt;

&lt;p&gt;I will also keep it up to date with the latest Flutter and Dart packages.&lt;/p&gt;

&lt;p&gt;So to recap, you'll get a few lessons for free here on YouTube. But the full course will be available on Teachable.&lt;/p&gt;

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

&lt;p&gt;This is not planned for now. I think I will be able to offer a better teaching experience on Teachable.&lt;/p&gt;

&lt;p&gt;I will offer this &lt;strong&gt;and future courses&lt;/strong&gt; on Teachable. And you'll be able to purchase multiple courses for a discounted price in a single bundle. This is not something that is possible with Udemy.&lt;/p&gt;

&lt;h2&gt;
  
  
  Course length
&lt;/h2&gt;

&lt;p&gt;The final course will likely have between 2 and 3 hours of content. &lt;/p&gt;

&lt;p&gt;As a crash course, it aims to get you up to speed with REST APIs in a short amount of time.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pricing
&lt;/h2&gt;

&lt;p&gt;The course is &lt;a href="https://courses.codewithandrea.com/"&gt;already on sale&lt;/a&gt; with an introductory price of $12. &lt;/p&gt;

&lt;p&gt;This includes the first chapter of the course, with an introduction to REST APIs.&lt;/p&gt;

&lt;p&gt;I'll try to add new content on a weekly basis. The course should be complete within the next couple of months.&lt;/p&gt;

&lt;h3&gt;
  
  
  Enroll today to get the course and all future updates for $12.
&lt;/h3&gt;

&lt;p&gt;The price will go up as I add more content.&lt;/p&gt;

&lt;p&gt;Now is the best time to purchase my course. You can enroll at this link:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://courses.codewithandrea.com/"&gt;courses.codewithandrea.com&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Happy coding!&lt;/p&gt;

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