<?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: Jordan Holland</title>
    <description>The latest articles on DEV Community by Jordan Holland (@jordanm_h).</description>
    <link>https://dev.to/jordanm_h</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%2F658900%2F44d4940f-7d32-4923-9f61-f24f27f7101c.png</url>
      <title>DEV Community: Jordan Holland</title>
      <link>https://dev.to/jordanm_h</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/jordanm_h"/>
    <language>en</language>
    <item>
      <title>Getting a substring in Dart</title>
      <dc:creator>Jordan Holland</dc:creator>
      <pubDate>Wed, 11 Aug 2021 04:01:03 +0000</pubDate>
      <link>https://dev.to/jordanm_h/getting-a-substring-in-dart-4pb7</link>
      <guid>https://dev.to/jordanm_h/getting-a-substring-in-dart-4pb7</guid>
      <description>&lt;p&gt;I was trying to figure out the most efficient way to trim or shorten a String in Dart(more speficially for a Flutter project) yesterday. There's actually a couple of different ways to do it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The &lt;code&gt;substring&lt;/code&gt; method
&lt;/h2&gt;

&lt;p&gt;The first and most typical one is using the &lt;a href="https://api.flutter.dev/flutter/dart-core/String/substring.html"&gt;substring&lt;/a&gt; method. The use case is pretty simple, you call &lt;code&gt;substring&lt;/code&gt; on your string and specify a start and end index:&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;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"developermemos"&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;portion&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="na"&gt;substring&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;9&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// developer&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;While it's easy to understand it wasn't great for my use case because I just wanted to shorten an existing string, and if you specify an end index that your string doesn't contain(for example 20 for the above case hypothetically) you will get a &lt;code&gt;RangeError&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The characters approach
&lt;/h2&gt;

&lt;p&gt;What I wanted to do was get the first x characters for a string that could potentially have a length of anything above 0. I found out that the easiest approach for this case is to use &lt;code&gt;.characters.take&lt;/code&gt; on the string, here's an 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;final&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"developermemos"&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;portion&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="na"&gt;characters&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;take&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;toString&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// developer&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The good thing about this approach is that you won't get a &lt;code&gt;RangeError&lt;/code&gt; like you would with &lt;code&gt;substring&lt;/code&gt; if you specify an index that is too high, it will just return the entire string 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="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"developermemos"&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;portion&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="na"&gt;characters&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;take&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="na"&gt;toString&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// developermemos&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This was perfect for my particular use case. The only caveat is that it seems like while the above will work without any imports in Flutter, if you are using plain Dart you need to add and import the &lt;a href="https://pub.dev/packages/characters"&gt;characters package&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Bonus: The takeLast method
&lt;/h2&gt;

&lt;p&gt;There's also another method called &lt;code&gt;takeLast&lt;/code&gt; that does pretty much the same thing as &lt;code&gt;take&lt;/code&gt; but in reverse, it will take the last x characters from a string. If you use a count that is higher than the length of the string itself it will just return the entire string. Here's a quick 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;final&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"developermemos"&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;portion&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="na"&gt;characters&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;takeLast&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="na"&gt;toString&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// memos&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>flutter</category>
      <category>dart</category>
    </item>
    <item>
      <title>Capturing a Flutter widget as an image using RepaintBoundary</title>
      <dc:creator>Jordan Holland</dc:creator>
      <pubDate>Wed, 04 Aug 2021 23:15:13 +0000</pubDate>
      <link>https://dev.to/jordanm_h/capturing-a-flutter-widget-as-an-image-using-repaintboundary-3k50</link>
      <guid>https://dev.to/jordanm_h/capturing-a-flutter-widget-as-an-image-using-repaintboundary-3k50</guid>
      <description>&lt;p&gt;The other day I decided I wanted to add a feature in one of my projects to share a graph and I was looking for ways to convert the graph into an image. In the end the approach that I landed on was using the RepaintBoundary widget and I'm going to explain how to use it in this post.&lt;/p&gt;

&lt;h2&gt;
  
  
  The widget
&lt;/h2&gt;

&lt;p&gt;First of all let's just start with a widget, a green Container with some text inside. Here's what the code for it looks like:&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;Container&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nl"&gt;decoration:&lt;/span&gt; &lt;span class="n"&gt;BoxDecoration&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nl"&gt;color:&lt;/span&gt; &lt;span class="n"&gt;Colors&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;green&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="nl"&gt;height:&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nl"&gt;width:&lt;/span&gt; &lt;span class="mi"&gt;400&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nl"&gt;child:&lt;/span&gt; &lt;span class="n"&gt;Center&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nl"&gt;child:&lt;/span&gt; &lt;span class="n"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="s"&gt;"Hello world!"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nl"&gt;style:&lt;/span&gt; &lt;span class="n"&gt;TextStyle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nl"&gt;color:&lt;/span&gt; &lt;span class="n"&gt;Colors&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;white&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nl"&gt;fontSize:&lt;/span&gt; &lt;span class="mi"&gt;24&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And here's what the above widget looks like visually(this was generated using &lt;a href="https://dartpad.dev" rel="noopener noreferrer"&gt;DartPad&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%2Fdevelopermemos.com%2Fstatic%2F0499a9dbad344119c721b8584b951e20%2F293b3%2Fexample_container.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%2Fdevelopermemos.com%2Fstatic%2F0499a9dbad344119c721b8584b951e20%2F293b3%2Fexample_container.png" alt="Container Widget"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrap it with RepaintBoundary
&lt;/h2&gt;

&lt;p&gt;To convert this widget to an image file(or capture/screenshot it) you need to wrap the widget in a &lt;code&gt;RepaintBoundary&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;RepaintBoundary&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nl"&gt;child:&lt;/span&gt; &lt;span class="n"&gt;Container&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nl"&gt;decoration:&lt;/span&gt; &lt;span class="n"&gt;BoxDecoration&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="nl"&gt;color:&lt;/span&gt; &lt;span class="n"&gt;Colors&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;green&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nl"&gt;height:&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nl"&gt;width:&lt;/span&gt; &lt;span class="mi"&gt;400&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nl"&gt;child:&lt;/span&gt; &lt;span class="n"&gt;Center&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="nl"&gt;child:&lt;/span&gt; &lt;span class="n"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="s"&gt;"Hello world!"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nl"&gt;style:&lt;/span&gt; &lt;span class="n"&gt;TextStyle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
          &lt;span class="nl"&gt;color:&lt;/span&gt; &lt;span class="n"&gt;Colors&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;white&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="nl"&gt;fontSize:&lt;/span&gt; &lt;span class="mi"&gt;24&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then you need to create a &lt;code&gt;GlobalKey&lt;/code&gt; and pass that to the &lt;code&gt;RepaintBoundary&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="kd"&gt;final&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;GlobalKey&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="p"&gt;...&lt;/span&gt;

&lt;span class="n"&gt;RepaintBoundary&lt;/span&gt;&lt;span class="p"&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="p"&gt;,&lt;/span&gt;
  &lt;span class="nl"&gt;child:&lt;/span&gt; &lt;span class="n"&gt;Container&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nl"&gt;decoration:&lt;/span&gt; &lt;span class="n"&gt;BoxDecoration&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="nl"&gt;color:&lt;/span&gt; &lt;span class="n"&gt;Colors&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;green&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nl"&gt;height:&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nl"&gt;width:&lt;/span&gt; &lt;span class="mi"&gt;400&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nl"&gt;child:&lt;/span&gt; &lt;span class="n"&gt;Center&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="nl"&gt;child:&lt;/span&gt; &lt;span class="n"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="s"&gt;"Hello world!"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nl"&gt;style:&lt;/span&gt; &lt;span class="n"&gt;TextStyle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
          &lt;span class="nl"&gt;color:&lt;/span&gt; &lt;span class="n"&gt;Colors&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;white&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="nl"&gt;fontSize:&lt;/span&gt; &lt;span class="mi"&gt;24&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Create the image
&lt;/h2&gt;

&lt;p&gt;Now the last step is to use the key above kind of like a controller and create an image representation of the widget wrapped inside &lt;code&gt;RepaintBoundary&lt;/code&gt;. I probably should also add that the widget you wrap doesn't have to be a &lt;code&gt;Container&lt;/code&gt; widget. Okay, onto the code for getting the bytes for an image. You could trigger this code with a button or something along those lines:&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;boundary&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="na"&gt;currentContext&lt;/span&gt;&lt;span class="o"&gt;?.&lt;/span&gt;&lt;span class="na"&gt;findRenderObject&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;RenderRepaintBoundary&lt;/span&gt;&lt;span class="o"&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;image&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;boundary&lt;/span&gt;&lt;span class="o"&gt;?.&lt;/span&gt;&lt;span class="na"&gt;toImage&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;byteData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;image&lt;/span&gt;&lt;span class="o"&gt;?.&lt;/span&gt;&lt;span class="na"&gt;toByteData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;format:&lt;/span&gt; &lt;span class="n"&gt;ImageByteFormat&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;png&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;imageBytes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;byteData&lt;/span&gt;&lt;span class="o"&gt;?.&lt;/span&gt;&lt;span class="na"&gt;buffer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;asUint8List&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then the next step is to write those bytes to a file somewhere(you will need the &lt;code&gt;path_provider&lt;/code&gt; package to use &lt;code&gt;getApplicationDocumentsDirectory&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="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;imageBytes&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="kc"&gt;null&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;directory&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;getApplicationDocumentsDirectory&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;imagePath&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;File&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'&lt;/span&gt;&lt;span class="si"&gt;${directory.path}&lt;/span&gt;&lt;span class="s"&gt;/container_image.png'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;create&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;imagePath&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;writeAsBytes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;imageBytes&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;And here is the full code for this step:&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;boundary&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="na"&gt;currentContext&lt;/span&gt;&lt;span class="o"&gt;?.&lt;/span&gt;&lt;span class="na"&gt;findRenderObject&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;RenderRepaintBoundary&lt;/span&gt;&lt;span class="o"&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;image&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;boundary&lt;/span&gt;&lt;span class="o"&gt;?.&lt;/span&gt;&lt;span class="na"&gt;toImage&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;byteData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;image&lt;/span&gt;&lt;span class="o"&gt;?.&lt;/span&gt;&lt;span class="na"&gt;toByteData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;format:&lt;/span&gt; &lt;span class="n"&gt;ImageByteFormat&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;png&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;imageBytes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;byteData&lt;/span&gt;&lt;span class="o"&gt;?.&lt;/span&gt;&lt;span class="na"&gt;buffer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;asUint8List&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;imageBytes&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="kc"&gt;null&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;directory&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;getApplicationDocumentsDirectory&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;imagePath&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;File&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'&lt;/span&gt;&lt;span class="si"&gt;${directory.path}&lt;/span&gt;&lt;span class="s"&gt;/container_image.png'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;create&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;imagePath&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;writeAsBytes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;imageBytes&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;Once you execute this code an image representation of the widget will be created in the applications document directory of your app. Here's the output I got after I executed the code on an iOS simulator:&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%2Fdevelopermemos.com%2Fstatic%2F7b171fdd526ed2a7c44472d96e5a1fee%2F6a8a8%2Fcontainer_image.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%2Fdevelopermemos.com%2Fstatic%2F7b171fdd526ed2a7c44472d96e5a1fee%2F6a8a8%2Fcontainer_image.png" alt="PNG Image Representation"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;By the way you can view the contents of a simulator's document directory using the following command on MacOS:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;open &lt;span class="sb"&gt;`&lt;/span&gt;xcrun simctl get_app_container booted &lt;span class="o"&gt;[&lt;/span&gt;Bundle ID] data&lt;span class="sb"&gt;`&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Some caveats
&lt;/h2&gt;

&lt;p&gt;I'll close this post with a couple of caveats with the approach above:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The resulting image might end up pixelated in some cases. You can rectify this by passing the &lt;code&gt;pixelRatio&lt;/code&gt; parameter when using &lt;code&gt;await boundary?.toImage()&lt;/code&gt;. You might want to combine this with &lt;code&gt;MediaQuery.of(context).devicePixelRatio&lt;/code&gt; for the best effect. I learnt about this from the README of an excellent package called &lt;a href="https://pub.dev/packages/screenshot" rel="noopener noreferrer"&gt;screenshot&lt;/a&gt;. (The reason I wrote my own implementation is because I already use a lot of packages in the project I was working on and didn't want to add any more...)&lt;/li&gt;
&lt;li&gt;The generated image will be in PNG format. I'm not sure if you can generate a JPEG image or how you would do it. I might end up investigating this in the future.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>flutter</category>
      <category>dart</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Excluding Dart files from static analysis</title>
      <dc:creator>Jordan Holland</dc:creator>
      <pubDate>Tue, 20 Jul 2021 02:32:02 +0000</pubDate>
      <link>https://dev.to/jordanm_h/excluding-dart-files-from-static-analysis-3c19</link>
      <guid>https://dev.to/jordanm_h/excluding-dart-files-from-static-analysis-3c19</guid>
      <description>&lt;p&gt;I wrote a couple of posts about linting this year, but this one is about excluding files from static analysis. After adding static analysis to most of my Flutter projects I found that sometimes there were files that I didn't want to be warned about.&lt;/p&gt;

&lt;p&gt;A good example of this is if you use something like &lt;code&gt;mockito&lt;/code&gt; or &lt;code&gt;json_serializable&lt;/code&gt;. When you implement these kinds of packages in your project you run &lt;code&gt;build_runner&lt;/code&gt; and they generate code for you. Sometimes the analyzer will pick up issues with the generated code. You're not going to edit generated code to squash linting issues(or you shouldn't edit it anyway). &lt;/p&gt;

&lt;p&gt;I got sick of the generated code files in my project showing up in the 'Problems' tab of VSCode so I finally decided to go digging for a solution this week and it was refreshingly straight forward. You just need to make some small changes to your &lt;strong&gt;analysis_options.yaml&lt;/strong&gt; file. So for example if your file looks something like this:&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;include&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;package:flutter_lints/flutter.yaml&lt;/span&gt;

&lt;span class="na"&gt;linter&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;rules&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;use_key_in_widget_constructors&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="no"&gt;false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You just need to add a key for &lt;code&gt;analyzer&lt;/code&gt; and add your exclusions below it with &lt;code&gt;exclude&lt;/code&gt;, like this:&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;include&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;package:flutter_lints/flutter.yaml&lt;/span&gt;

&lt;span class="na"&gt;analyzer&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;exclude&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;lib/ui/something/file1.dart'&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;lib/data/something/file2.dart'&lt;/span&gt;  

&lt;span class="na"&gt;linter&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;rules&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;use_key_in_widget_constructors&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="no"&gt;false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can also use '**' to target specific file patterns, so if you wanted to ignore all the &lt;code&gt;.mocks.dart&lt;/code&gt; files in a specific test directory you could do something like this:&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;include&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;package:flutter_lints/flutter.yaml&lt;/span&gt;

&lt;span class="na"&gt;analyzer&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;exclude&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;lib/ui/something/file1.dart'&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;test/data/notifiers/**.mocks.dart'&lt;/span&gt;  

&lt;span class="na"&gt;linter&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;rules&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;use_key_in_widget_constructors&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="no"&gt;false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can also target all files with a specific pattern globally too. In my project I wanted to exclude all files with &lt;code&gt;.mocks.dart&lt;/code&gt; and &lt;code&gt;.g.dart&lt;/code&gt; so I ended up with these settings:&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;include&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;package:flutter_lints/flutter.yaml&lt;/span&gt;

&lt;span class="na"&gt;analyzer&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;exclude&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;**.g.dart'&lt;/span&gt;  
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;**.mocks.dart'&lt;/span&gt;

&lt;span class="na"&gt;linter&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;rules&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;use_key_in_widget_constructors&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="no"&gt;false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above examples worked for me in a Flutter project with &lt;code&gt;sdk: "&amp;gt;=2.12.0 &amp;lt;3.0.0"&lt;/code&gt;, and you can find more discussion about the topic &lt;a href="https://github.com/dart-lang/sdk/issues/25551"&gt;here&lt;/a&gt;. It looks like the are some reports recently about issues with Dart 2.13.0 though 😅. And speaking of linting, if you want to hear my (very brief) thoughts about &lt;strong&gt;flutter_lints&lt;/strong&gt; then &lt;a href="https://developermemos.com/posts/trying-flutter-lints-package"&gt;check out my post&lt;/a&gt; from the other week.&lt;/p&gt;

</description>
      <category>flutter</category>
      <category>dart</category>
      <category>mobile</category>
      <category>tooling</category>
    </item>
    <item>
      <title>Run Flutter tests with GitHub Actions</title>
      <dc:creator>Jordan Holland</dc:creator>
      <pubDate>Sat, 10 Jul 2021 00:05:56 +0000</pubDate>
      <link>https://dev.to/jordanm_h/run-flutter-tests-with-github-actions-8ll</link>
      <guid>https://dev.to/jordanm_h/run-flutter-tests-with-github-actions-8ll</guid>
      <description>&lt;p&gt;If you're like me you probably like setting your project up to automatically run your tests when you create a Pull Request on GitHub. I wrote another post &lt;a href="https://developermemos.com/posts/automate-flutter-package-upgrades-github"&gt;about upgrading Flutter packages with GitHub Actions&lt;/a&gt; in May but I realised today that I never wrote a post about running tests, so here we go.&lt;/p&gt;

&lt;h2&gt;
  
  
  Run Flutter tests with GitHub Actions
&lt;/h2&gt;

&lt;p&gt;There isn't an Action on the marketplace that does all of the steps for you. It's still pretty easy to set things up but, for installing Flutter I always use &lt;a href="https://github.com/marketplace/actions/flutter-action"&gt;subosito/flutter-action@v1&lt;/a&gt;. Here are the rough steps that I want my action to perform:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Checkout the project&lt;/li&gt;
&lt;li&gt;Caching(optional because it only saves around 30 seconds or so)&lt;/li&gt;
&lt;li&gt;Install Flutter&lt;/li&gt;
&lt;li&gt;Run &lt;code&gt;pub get&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Run the tests&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  The file for the action
&lt;/h2&gt;

&lt;p&gt;So with the steps written above this is what we roughly end up with:&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;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Run Tests(for PRs)&lt;/span&gt;

&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;workflow_dispatch&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="c1"&gt;# Runs when a PR is made against master branch &lt;/span&gt;
  &lt;span class="na"&gt;pull_request&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt; &lt;span class="nv"&gt;master&lt;/span&gt; &lt;span class="pi"&gt;]&lt;/span&gt;

&lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;flutter_version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;2.2.3"&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;run_tests&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;

    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v2&lt;/span&gt;
      &lt;span class="c1"&gt;# Cache Flutter environment&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Cache Flutter dependencies&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/cache@v2&lt;/span&gt;
        &lt;span class="na"&gt;with&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;/opt/hostedtoolcache/flutter&lt;/span&gt;
          &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ runner.OS }}-flutter-install-cache-${{ env.flutter_version }}&lt;/span&gt;  
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;subosito/flutter-action@v1&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;flutter-version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ env.flutter_version }}&lt;/span&gt;
          &lt;span class="na"&gt;channel&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;stable&lt;/span&gt; 
      &lt;span class="c1"&gt;# Run pub get &lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Run pub get&lt;/span&gt;   
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;flutter pub get&lt;/span&gt;
      &lt;span class="c1"&gt;# Runs tests&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Run tests&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;flutter test&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Tinkering
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;The above action will run whenever you create a Pull Request against the &lt;code&gt;master&lt;/code&gt; branch. You could change this to whatever your default branch is, you can even define multiple branches. &lt;/li&gt;
&lt;li&gt;I also added &lt;code&gt;workflow_dispatch&lt;/code&gt; so the action can be run manually - the reason I did this is because the cache doesn't seem to build properly unless you run the action on the base branch once(this seems to be by design &lt;a href="https://docs.github.com/en/actions/guides/caching-dependencies-to-speed-up-workflows#restrictions-for-accessing-a-cache"&gt;according to GitHub&lt;/a&gt;). &lt;/li&gt;
&lt;li&gt;You can also change the Flutter version around to your liking, the action above is pinned to 2.2.3 which is the latest stable version at this time. In some of my projects I started specifying &lt;code&gt;2.x&lt;/code&gt; for the version(but tossed out caching) so I don't have to update my actions every couple of weeks.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Potential Improvements
&lt;/h2&gt;

&lt;p&gt;I think the only thing you could potentially add to the above action is something to build the project at the end like &lt;code&gt;flutter build ios&lt;/code&gt; or &lt;code&gt;flutter build apk&lt;/code&gt;. If your unit tests don't have great coverage you could potentially break your project and I'm pretty sure your tests would still run without any issues. Adding a build step to the end would make sure that your project still builds correctly, but keep in mind this would make the action take longer to finish.&lt;/p&gt;

</description>
      <category>flutter</category>
      <category>dart</category>
      <category>github</category>
    </item>
    <item>
      <title>Automate Flutter package upgrades with GitHub Actions(a Dependabot alternative)</title>
      <dc:creator>Jordan Holland</dc:creator>
      <pubDate>Mon, 05 Jul 2021 03:16:06 +0000</pubDate>
      <link>https://dev.to/jordanm_h/automate-flutter-package-upgrades-with-github-actions-a-dependabot-alternative-3hg3</link>
      <guid>https://dev.to/jordanm_h/automate-flutter-package-upgrades-with-github-actions-a-dependabot-alternative-3hg3</guid>
      <description>&lt;p&gt;Like with pretty much any other framework, keeping up with package upgrades in Flutter can get pretty tedious. I decided to see if I could make things a little less tedious over the weekend and I'd like to share a GitHub Action workflow that I came up with while experimenting.&lt;/p&gt;

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

&lt;p&gt;I'd actually be happy to use Dependabot but there isn't full support yet. Somebody is &lt;a href="https://github.com/dependabot/dependabot-core/pull/3438"&gt;working on it&lt;/a&gt; at the moment though. I'm confident there will be full support one day, it's just a matter of time. For now though Dependabot isn't really a realistic option.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using GitHub Actions
&lt;/h2&gt;

&lt;p&gt;There was the option of creating an Action and putting it on the Actions Marketplace but I'm not entirely sure what that would involve yet and I'm not that committed to the idea yet either considering that there is work being done on the Dependabot front. So in the end I just decided to create a workflow with existing Marketplace Actions. Here's roughly the set of steps I wanted the workflow to use:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Check out the repo&lt;/li&gt;
&lt;li&gt;Pull in cache data(so the next step runs a little faster)&lt;/li&gt;
&lt;li&gt;Setup Flutter CLI so it can be used in the next steps&lt;/li&gt;
&lt;li&gt;Run &lt;code&gt;flutter pub upgrade --major-versions&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Run &lt;code&gt;flutter pub get&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Run &lt;code&gt;flutter test&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;(Optional) Capture the output of &lt;code&gt;flutter pub outdated&lt;/code&gt; for later&lt;/li&gt;
&lt;li&gt;If there are changes from (4) commit them to a new branch and open a PR&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;And obviously I'd want this workflow to run every so often so it would need to be scheduled with cron. In the end this is what I came up with:&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;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Upgrade packages&lt;/span&gt;

&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;workflow_dispatch&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;schedule&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;cron&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;0&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;0&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;*&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;*&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;*"&lt;/span&gt;

&lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;flutter_version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;2.2.2"&lt;/span&gt;

&lt;span class="c1"&gt;# A workflow run is made up of one or more jobs that can run sequentially or in parallel&lt;/span&gt;
&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;upgrade_packages&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="c1"&gt;# The type of runner that the job will run on&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;

    &lt;span class="c1"&gt;# Steps represent a sequence of tasks that will be executed as part of the job&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="c1"&gt;# Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v2&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Cache Flutter dependencies&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/cache@v2&lt;/span&gt;
        &lt;span class="na"&gt;with&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;/opt/hostedtoolcache/flutter&lt;/span&gt;
          &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ runner.OS }}-flutter-install-cache-${{ env.flutter_version }}&lt;/span&gt;  
      &lt;span class="c1"&gt;# Installs Flutter    &lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;subosito/flutter-action@v1&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;flutter-version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ env.flutter_version }}&lt;/span&gt;
          &lt;span class="na"&gt;channel&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;stable&lt;/span&gt;   
      &lt;span class="c1"&gt;# Upgrade packages(bump major versions)    &lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Run upgrade&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;flutter pub upgrade --major-versions&lt;/span&gt;
      &lt;span class="c1"&gt;# Get/install packages  &lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Run get&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;flutter pub get&lt;/span&gt;  
      &lt;span class="c1"&gt;# Run tests  &lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Run tests&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;flutter test&lt;/span&gt;
      &lt;span class="c1"&gt;# Captures the output of `flutter pub outdated`  &lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Check remaining outdated packages&lt;/span&gt;
        &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;check_outdated&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
          &lt;span class="s"&gt;content="$(flutter pub outdated)"&lt;/span&gt;
          &lt;span class="s"&gt;content="${content//'%'/'%25'}"&lt;/span&gt;
          &lt;span class="s"&gt;content="${content//$'\n'/'%0A'}"&lt;/span&gt;
          &lt;span class="s"&gt;content="${content//$'\r'/'%0D'}"&lt;/span&gt;
          &lt;span class="s"&gt;echo "::set-output name=outdated_info::$content"&lt;/span&gt;
      &lt;span class="c1"&gt;# Opens a pull request with changes    &lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Create Pull Request&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;peter-evans/create-pull-request@v3&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;token&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.PAT }}&lt;/span&gt;
            &lt;span class="na"&gt;commit-message&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Upgrade packages&lt;/span&gt;
            &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Upgrade packages&lt;/span&gt;
            &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt; 
              &lt;span class="s"&gt;Output for outdated check following upgrades:&lt;/span&gt;
              &lt;span class="s"&gt;${{ steps.check_outdated.outputs.outdated_info }}&lt;/span&gt;
            &lt;span class="na"&gt;branch&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;feature/update-packages&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For this to work you need to generate a &lt;code&gt;Personal Access Token&lt;/code&gt; in your GitHub account's settings and then add that as a secret to your repository. You can learn more about this &lt;a href="https://docs.github.com/en/github/authenticating-to-github/keeping-your-account-and-data-secure/creating-a-personal-access-token"&gt;here&lt;/a&gt;. This is what the &lt;code&gt;${{ secrets.PAT }}&lt;/code&gt; value represents in the last step.&lt;/p&gt;

&lt;p&gt;You might have also noticed that I have this set to run everyday at 12am UTC. I'm going to tweak this later on but like I said I'm just experimenting with things at the moment and want to see if I run into any issues down the road. If I find some improvements I can make I will update this post. If you wanted to run this on a weekly schedule instead, you could use something like "0 0 * * Sun" instead(12am UTC every Sunday).&lt;/p&gt;

&lt;h2&gt;
  
  
  Caveats
&lt;/h2&gt;

&lt;p&gt;The above workflow has been working pretty good for me for the last few days on some simple, small projects. That being said it is far from perfect. &lt;/p&gt;

&lt;p&gt;First of all the above workflow won't upgrade your Pods on the iOS side of things. If you switch from &lt;code&gt;ubuntu-latest&lt;/code&gt; to &lt;code&gt;macos-latest&lt;/code&gt; you could run &lt;code&gt;pod install --repo-update&lt;/code&gt; in the ios directory of your project, I did try this out personally and it seemed to work okay - but keep in mind that workflows that use MacOS cost &lt;a href="https://pmagentur.com/wissen/technologie/github-actions-pricing/"&gt;something like 10 times more than workflows that use Ubuntu&lt;/a&gt;. This would probably matter less if you were only running the workflow once a week or something like that.&lt;/p&gt;

&lt;p&gt;Another thing you could tweak is the &lt;code&gt;flutter pub upgrade --major-versions&lt;/code&gt; command. This command will potentially pull in breaking changes because it will upgrade over major versions. You can opt out of this behaviour by just running &lt;code&gt;flutter pub upgrade&lt;/code&gt; instead. &lt;/p&gt;

&lt;p&gt;One more shortcoming of the workflow above is that it only runs your tests. Your tests might not cover everything so adding a &lt;code&gt;flutter build ios&lt;/code&gt; or &lt;code&gt;flutter build apk&lt;/code&gt; might add an extra layer of security if the upgrades break your project. I think I'm going to look into all of these points as I keep tweaking the workflow.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summing up
&lt;/h2&gt;

&lt;p&gt;Like I said the workflow I introduced above definitely isn't perfect but I think that it's a good start and something that can be used to keep sane while we all wait for Dependabot support. If you're interested in more Flutter tips, I wrote another post about adding linting to a project a couple of days ago - you can find it &lt;a href="https://developermemos.com/posts/linting-flutter-projects"&gt;here&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>flutter</category>
      <category>github</category>
      <category>dependabot</category>
      <category>actions</category>
    </item>
    <item>
      <title>Trying out the flutter_lints package</title>
      <dc:creator>Jordan Holland</dc:creator>
      <pubDate>Thu, 01 Jul 2021 03:48:02 +0000</pubDate>
      <link>https://dev.to/jordanm_h/trying-out-the-flutterlints-package-4bp9</link>
      <guid>https://dev.to/jordanm_h/trying-out-the-flutterlints-package-4bp9</guid>
      <description>&lt;p&gt;I made another post &lt;a href="https://developermemos.com/posts/linting-flutter-projects"&gt;last month&lt;/a&gt; about using linting in Flutter projects but the other day I found out about a (relatively) new package called flutter_lints so I thought I'd try it out and give my impressions.&lt;/p&gt;

&lt;h2&gt;
  
  
  The (somewhat) older options
&lt;/h2&gt;

&lt;p&gt;If you read my other post or use linting in your Flutter projects you'll probably already know that there were two major options up until now for linting:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://pub.dev/packages/lints"&gt;lints&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;
&lt;a href="https://pub.dev/packages/pedantic/install"&gt;pedantic&lt;/a&gt; (used internally at Google?)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I've used both and they are both pretty good, I use lints a lot more often though. I kind of get the feeling that lints is a little stricter but that just might be my imagination. &lt;/p&gt;

&lt;h2&gt;
  
  
  The new challenger(flutter_lints)
&lt;/h2&gt;

&lt;p&gt;So I was browsing Twitter the other day and I saw a &lt;a href="https://twitter.com/redbrogdon/status/1405307830135971842"&gt;tweet&lt;/a&gt; in my timeline about &lt;code&gt;flutter_lints&lt;/code&gt;. It looks like this package is actually endorsed and maintained by the Flutter Team. According to the pub.dev page it's built on top of the &lt;code&gt;lints&lt;/code&gt; package I mentioned above:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;This package is built on top of Dart's recommended.yaml set of lints from package:lints.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I also saw something else cool in the README:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Flutter apps, packages, and plugins created with flutter create starting with Flutter version 2.xx are already set up to use the lints defined in this package. Entities created before that version can use these lints by following these instructions:
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It looks like this is going to come bundled automatically when you set up a new project from now on? I created a new Flutter project with 2.2.2 two days or so ago and couldn't confirm this but, so maybe it's something that hasn't landed on stable yet.&lt;/p&gt;

&lt;h2&gt;
  
  
  My impressions
&lt;/h2&gt;

&lt;p&gt;So I decided to add &lt;code&gt;flutter_lints&lt;/code&gt; to one of my older projects and take it for a test drive. If you need steps on how to do this you can check out my &lt;a href="https://developermemos.com/posts/linting-flutter-projects"&gt;post from last month&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Unsurprisingly I found it to be really similar to &lt;code&gt;lints&lt;/code&gt;, but I did notice I got a lot of 'Use widget key in constructors' warnings in my custom widgets. This warning is definitely fair, I just hadn't seen it before with &lt;code&gt;lints&lt;/code&gt; or &lt;code&gt;pedantic&lt;/code&gt;. Apart from that I mostly got the same warnings as with the other options, especially about adding const keywords 😅.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--5rAkTf1q--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3gu2pjo8vu5c33w7dv09.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--5rAkTf1q--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3gu2pjo8vu5c33w7dv09.png" alt="Flutter Lint Warnings"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If this ends up automatically being added to all new projects it will be great, it'll take another step off my setup process. Plus, I never used to use any linting in my Flutter projects until a couple of months ago and I kind of regret not doing it sooner - it will definitely make things a lot cleaner and streamlined for newcomers.&lt;/p&gt;

</description>
      <category>flutter</category>
      <category>mobile</category>
      <category>dart</category>
    </item>
    <item>
      <title>Mixing packages that don't support null safety in Flutter</title>
      <dc:creator>Jordan Holland</dc:creator>
      <pubDate>Wed, 30 Jun 2021 03:43:26 +0000</pubDate>
      <link>https://dev.to/jordanm_h/mixing-packages-that-don-t-support-null-safety-in-flutter-2lef</link>
      <guid>https://dev.to/jordanm_h/mixing-packages-that-don-t-support-null-safety-in-flutter-2lef</guid>
      <description>&lt;p&gt;Null safety has been supported for a few months now in Dart and Flutter. I've migrated pretty much all of my projects to null safety without any issues but in some cases you might be waiting on a particular package that isn't supported yet. It's actually possible to use packages that don't support null safety in your project and still migrate to null safety. It's even possible to slowly migrate your project piece by piece to null safety too.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using outdated packages(that don't support null safety)
&lt;/h2&gt;

&lt;p&gt;I ended up in this precidament with one of my projects because I made the mistake of depending on &lt;a href="https://pub.dev/packages/charts_flutter"&gt;charts_flutter&lt;/a&gt;. The package itself is great but Google is pretty terrible at keeping the GitHub mirror up to date with their internal repo. That's a story for another day though...Anyway there was only one package in my project holding me back from going to null safety. Building without null safety requires passing an extra command line flag, that's why I put things off for so long but in the end I gave in. So if you want to use outdated packages in your project(that has migrated to null safety) you need to add this to basically every command: &lt;code&gt;--no-sound-null-safety&lt;/code&gt;. So if you were running &lt;code&gt;flutter run&lt;/code&gt; you would do it like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;flutter run &lt;span class="nt"&gt;--no-sound-null-safety&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Same goes for your tests as well:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;flutter &lt;span class="nb"&gt;test&lt;/span&gt; &lt;span class="nt"&gt;--no-sound-null-safety&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Declaring the Dart version of your entry point
&lt;/h2&gt;

&lt;p&gt;There's also another option of adding &lt;code&gt;// @dart=2.9&lt;/code&gt; to the top of the entry point(main.dart) of your app:&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;// @dart=2.9&lt;/span&gt;

&lt;span class="n"&gt;main&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&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I personally like this option better but doing this won't extend to your tests, so you either have to pin the dart version of all of your tests to 2.9 or use the &lt;code&gt;--no-sound-null-safety&lt;/code&gt; flag. You can use the version pinning above to slowly migrate your project files too, which is pretty good if you would like to break your migration up into small commits(but still keep everything working between each commit).&lt;/p&gt;

&lt;p&gt;In the end I just opted for using &lt;code&gt;--no-sound-null-safety&lt;/code&gt; because I wanted to migrate all of my tests too. By the way, you still have to pass this flag even when you're doing stuff like building APK files:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;fvm flutter build apk &lt;span class="nt"&gt;--split-per-abi&lt;/span&gt; &lt;span class="nt"&gt;--no-sound-null-safety&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I'm gunna try fiddling with the entry point version pinning in the future to see if I can work around this somehow.&lt;/p&gt;

&lt;h2&gt;
  
  
  But this doesn't work with Visual Studio Code...
&lt;/h2&gt;

&lt;p&gt;Yeah I noticed this myself too... To get all of this working with VSC(including your tests) you need to change some settings. Open your preferences and then select 'Workspace', then type 'args' into the search bar. After that select 'Dart &amp;amp; Flutter' from Extensions in the left pane. After this you should see settings for passing additional arguments to a bunch of different Flutter commands. You need to add &lt;code&gt;--no-sound-null-safety&lt;/code&gt; to the ones that are relevant to you. You could opt to pass it to all &lt;code&gt;flutter&lt;/code&gt; CLI commands too. I just added it for run and test in the end. Here's a screenshot of my setup for reference:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--2chWDNfa--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8o2c8ael09duq5sjxxp5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--2chWDNfa--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8o2c8ael09duq5sjxxp5.png" alt="Visual Studio Code Settings"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The pains of null safety migration
&lt;/h2&gt;

&lt;p&gt;Null safety support was a pretty big change. I think it was worth it too, and I'm really glad that there is atleast an option to choose to build/run without complete null safety. I do kind of wish Google would keep their repos up to date though...Even if it is just a mirror of an internal project... But I guess that is just how open source is so I can't really complain too much.&lt;/p&gt;

</description>
      <category>flutter</category>
      <category>mobile</category>
      <category>programming</category>
    </item>
  </channel>
</rss>
