<?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: Rene Lazo Mendez</title>
    <description>The latest articles on DEV Community by Rene Lazo Mendez (@rlazom).</description>
    <link>https://dev.to/rlazom</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%2F436422%2Fb1f96ab0-c6b5-4020-a739-fb09ca544818.jpg</url>
      <title>DEV Community: Rene Lazo Mendez</title>
      <link>https://dev.to/rlazom</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/rlazom"/>
    <language>en</language>
    <item>
      <title>Null or Nothing? Unmasking the Mystery of Parameters in Dart</title>
      <dc:creator>Rene Lazo Mendez</dc:creator>
      <pubDate>Sun, 19 May 2024 20:46:19 +0000</pubDate>
      <link>https://dev.to/rlazom/null-or-nothing-unmasking-the-mystery-of-parameters-in-dart-14bl</link>
      <guid>https://dev.to/rlazom/null-or-nothing-unmasking-the-mystery-of-parameters-in-dart-14bl</guid>
      <description>&lt;p&gt;Sometimes, in the world of development, things get a little confusing. Is a parameter &lt;strong&gt;&lt;em&gt;null&lt;/em&gt;&lt;/strong&gt; because it was explicitly passed that way, or simply because it wasn't specified? It's like trying to decipher a riddle: was it a "no" or a "don't know"?&lt;/p&gt;

&lt;p&gt;In Dart, the distinction between a &lt;strong&gt;&lt;em&gt;null&lt;/em&gt;&lt;/strong&gt; parameter and one that hasn't been specified can be crucial. To prevent our code from turning into a soup of letters, we need a way to unmask this mystery.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Introducing the Marker Technique!&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Imagine a magical object called &lt;strong&gt;_&lt;em&gt;unspecified&lt;/em&gt;&lt;/strong&gt;. This object holds no information, it merely exists to tell us that a parameter hasn't been defined. With a bit of code magic, we can use this object as a beacon to distinguish between an intentional &lt;strong&gt;&lt;em&gt;null&lt;/em&gt;&lt;/strong&gt; and a lack of information.&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="kt"&gt;Object&lt;/span&gt; &lt;span class="n"&gt;_unspecified&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, let's create a function that looks for this magical object:&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;bool&lt;/span&gt; &lt;span class="nf"&gt;_isUnspecified&lt;/span&gt;&lt;span class="p"&gt;(&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;identical&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_unspecified&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In our code, we can use this function to figure out if a parameter is &lt;strong&gt;&lt;em&gt;null&lt;/em&gt;&lt;/strong&gt; by design, or if it was simply not passed.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;A Practical Example!&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Let's imagine the SpaceState class. In its copyWith function, we want the successMessage and errorMessage parameters to be able to be &lt;strong&gt;&lt;em&gt;null&lt;/em&gt;&lt;/strong&gt;, but we also want the possibility for them to simply not be specified, preserving the original 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;SpaceState&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;isLoading&lt;/span&gt;&lt;span class="p"&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;successMessage&lt;/span&gt;&lt;span class="p"&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;errorMessage&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="n"&gt;SpaceState&lt;/span&gt; &lt;span class="n"&gt;copyWith&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="n"&gt;isLoading&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="kt"&gt;Object&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="n"&gt;successMessage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;_unspecified&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="kt"&gt;Object&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="n"&gt;errorMessage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;_unspecified&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;SpaceState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="nl"&gt;isLoading:&lt;/span&gt; &lt;span class="n"&gt;isLoading&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;isLoading&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nl"&gt;successMessage:&lt;/span&gt; &lt;span class="n"&gt;_isUnspecified&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;successMessage&lt;/span&gt;&lt;span class="p"&gt;)&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;successMessage&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;successMessage&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nl"&gt;errorMessage:&lt;/span&gt; &lt;span class="n"&gt;_isUnspecified&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;errorMessage&lt;/span&gt;&lt;span class="p"&gt;)&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;errorMessage&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;errorMessage&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="o"&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;&lt;strong&gt;Eureka!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;With this approach, we can avoid errors and keep our code clean and readable. The &lt;strong&gt;marker technique&lt;/strong&gt; allows us to differentiate between "&lt;strong&gt;&lt;em&gt;null&lt;/em&gt;&lt;/strong&gt;" and "&lt;strong&gt;&lt;em&gt;not specified&lt;/em&gt;&lt;/strong&gt;" with a clarity that brings us closer to achieving perfection in our code.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Remember:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;strong&gt;marker technique&lt;/strong&gt; is a creative and flexible solution, but it can also add a bit of complexity to your code.&lt;/li&gt;
&lt;li&gt;It's crucial to maintain consistency in using the marker to avoid confusion and errors.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With this technique, your code will speak clearly and help you create robust and easy-to-understand applications!&lt;/p&gt;

</description>
      <category>flutter</category>
      <category>dart</category>
      <category>tip</category>
      <category>null</category>
    </item>
    <item>
      <title>Resume Downloads in Flutter with Dio</title>
      <dc:creator>Rene Lazo Mendez</dc:creator>
      <pubDate>Wed, 26 Apr 2023 20:46:09 +0000</pubDate>
      <link>https://dev.to/rlazom/resume-downloads-in-flutter-with-dio-abc</link>
      <guid>https://dev.to/rlazom/resume-downloads-in-flutter-with-dio-abc</guid>
      <description>&lt;p&gt;Add the ability to resume downloads in your Flutter app&lt;/p&gt;

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

&lt;p&gt;By the end of this post, you will be able to download files, handle incomplete downloads, resume downloads, cancel, get current download status (percentage or size remaining) and merge all chunks into one file.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Current issue&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;I was facing a problem with my current project. I need to handle large video files, sometimes the download would not complete and every time the user accesses this specific view the download starts again from the beginning.&lt;/p&gt;

&lt;p&gt;At the time of writing this post, the &lt;a href="https://pub.dev/packages/dio"&gt;dio plugin&lt;/a&gt; does not have the ability to append data to an existing file during the download.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;So, what can we do?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;We are going to implement a customized procedure to handle our business logic.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Imports&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;We are going to need to add some dependencies to help us with the implementation of our service.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://pub.dev/packages/dio"&gt;dio: 5.1.1&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://pub.dev/packages/path"&gt;path: 1.8.3&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&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:dio/dio.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:path/path.dart'&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  &lt;strong&gt;Procedure Parameters&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;We will receive the &lt;strong&gt;remote url of the file&lt;/strong&gt; (&lt;em&gt;fileUrl&lt;/em&gt;) to download and the &lt;strong&gt;local route of the file&lt;/strong&gt; (&lt;em&gt;fileLocalRouteStr&lt;/em&gt;) in our user’s local storage.&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="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;File&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;getItemFileWithProgress&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="kd"&gt;required&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="n"&gt;fileUrl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
  &lt;span class="kd"&gt;required&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="n"&gt;fileLocalRouteStr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="kd"&gt;async&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;
  
  
  &lt;strong&gt;Local Variables&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Let’s first create an instance of the &lt;strong&gt;Dio&lt;/strong&gt; class and the necessary variables to handle the file path so we can “play” with the filename.&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;Dio&lt;/span&gt; &lt;span class="n"&gt;dio&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Dio&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="n"&gt;File&lt;/span&gt; &lt;span class="n"&gt;localFile&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;File&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fileLocalRouteStr&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;dir&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="na"&gt;dirname&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fileLocalRouteStr&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;basename&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="na"&gt;basenameWithoutExtension&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fileLocalRouteStr&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;extension&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="na"&gt;extension&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fileLocalRouteStr&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;localRouteToSaveFileStr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;fileLocalRouteStr&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now let’s check if the local file exists.&lt;br&gt;
&lt;code&gt;bool existsSync = localFile.existsSync();&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;If the local file &lt;strong&gt;DO NOT EXIST&lt;/strong&gt;, then we are in the &lt;em&gt;best case scenario&lt;/em&gt; where we are going to start the download from scratch. But if the file &lt;strong&gt;DO EXIST&lt;/strong&gt; then we need to do some magic.&lt;/p&gt;
&lt;h2&gt;
  
  
  &lt;strong&gt;The Magic ✨&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;First let’s get the source file size, then the local file size and add it to a list containing all chunk (file part) sizes.&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;existsSync&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;Response&lt;/span&gt; &lt;span class="n"&gt;response&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;dio&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;head&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fileUrl&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;totalBytes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'content-length'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;!&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;fileLocalSize&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;localFile&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;lengthSync&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="kt"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;sizes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;fileLocalSize&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We will create as many chunks of the file as needed and of course this number will be unknown so we will iterate over time until the (temporary) chunk file does not exists and each iteration will modify the chunk file name and add this chunk size to our list of sizes (we’ll need to know the sum of all sizes eventually).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;int i = 1;
localRouteToSaveFileStr = '$dir/$basename''_$i$extension';
File _f = File(localRouteToSaveFileStr);
while (_f.existsSync()) {
  sizes.add(_f.lengthSync());
  i++;
  localRouteToSaveFileStr = '$dir/$basename''_$i$extension';
  _f = File(localRouteToSaveFileStr);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When the code exits the &lt;em&gt;while loop&lt;/em&gt;, we have the new chunk-file ready to store the remaining bytes of the file. So we’ll need to add up the sizes so far and create the &lt;em&gt;Options&lt;/em&gt; for the header in the download.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  int sumSizes = sizes.fold(0, (p, c) =&amp;gt; p + c);
  Options options = Options(
    headers: {'Range': 'bytes=$sumSizes-'},
  );
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;We’re saying here, on the next download fetch only from this byte (sumSizes) forward to the end of the file (we could also specify the end range of bytes, but it’s not necessary in this case)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;End of The magic ;)&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Merge all chunks of the file&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Wait, we still have to do a few things with all the chunk files. If the &lt;em&gt;localFile&lt;/em&gt; exists, then we need to merge all the small pieces of the original file into one and delete the chunks after.&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;existsSync&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="n"&gt;raf&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;localFile&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;mode:&lt;/span&gt; &lt;span class="n"&gt;FileMode&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;writeOnlyAppend&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;i&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="kt"&gt;String&lt;/span&gt; &lt;span class="n"&gt;filePartLocalRouteStr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;'&lt;/span&gt;&lt;span class="si"&gt;$dir&lt;/span&gt;&lt;span class="s"&gt;/&lt;/span&gt;&lt;span class="si"&gt;$basename&lt;/span&gt;&lt;span class="s"&gt;''_&lt;/span&gt;&lt;span class="si"&gt;$i$extension&lt;/span&gt;&lt;span class="s"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="n"&gt;File&lt;/span&gt; &lt;span class="n"&gt;_f&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;File&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;filePartLocalRouteStr&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_f&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;existsSync&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;raf&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;raf&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;writeFrom&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;_f&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;readAsBytes&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;_f&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;delete&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;filePartLocalRouteStr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;'&lt;/span&gt;&lt;span class="si"&gt;$dir&lt;/span&gt;&lt;span class="s"&gt;/&lt;/span&gt;&lt;span class="si"&gt;$basename&lt;/span&gt;&lt;span class="s"&gt;''_&lt;/span&gt;&lt;span class="si"&gt;$i$extension&lt;/span&gt;&lt;span class="s"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;_f&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;File&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;filePartLocalRouteStr&lt;/span&gt;&lt;span class="p"&gt;);&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;raf&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;close&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;localFile&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We’ll open the &lt;em&gt;localFile&lt;/em&gt; in write mode, but we’ll only adding the new bytes at the end (append), so we won’t overwrite what’s already there. Very similar to what we did before, we’ll iterate until the chunk filename doesn’t exist and then return the &lt;strong&gt;FULL FILE. 🥳&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;BONUS: Download progress &amp;amp; Cancel download&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Let’s add 2 more variables to the environment&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;CancelToken&lt;/span&gt; &lt;span class="n"&gt;cancelToken&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;CancelToken&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;percentNotifier&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ValueNotifier&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;double&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first one will be “&lt;strong&gt;&lt;em&gt;cancelToken&lt;/em&gt;&lt;/strong&gt;” to give us the possibility to cancel the current download, and the “&lt;strong&gt;&lt;em&gt;percentNotifier&lt;/em&gt;&lt;/strong&gt;” will help us to listen only to the percent changes so we don’t have to redraw all the screen, instead of only the desired widget.&lt;/p&gt;

&lt;p&gt;Now we’ll need 2 more procedures to handle this new logic.&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;_cancel&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;cancelToken&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;cancel&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="n"&gt;percentNotifier&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="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="n"&gt;_onReceiveProgress&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;received&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;total&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;cancelToken&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;isCancelled&lt;/span&gt;&lt;span class="p"&gt;)&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;sum&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sizes&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;fold&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;c&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;p&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;received&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;percentNotifier&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;received&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;total&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;Before executing the download we’ll need to check if the cancel token was already used and if so, refresh the variable with a new 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="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cancelToken&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;isCancelled&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;cancelToken&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;CancelToken&lt;/span&gt;&lt;span class="p"&gt;();&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;dio&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;download&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="n"&gt;fileUrl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;localRouteToSaveFileStr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nl"&gt;options:&lt;/span&gt; &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nl"&gt;cancelToken:&lt;/span&gt; &lt;span class="n"&gt;cancelToken&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nl"&gt;deleteOnError:&lt;/span&gt; &lt;span class="kc"&gt;false&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;&lt;em&gt;“&lt;strong&gt;deleteOnError&lt;/strong&gt;” parameter in &lt;strong&gt;false&lt;/strong&gt; will allow us to cancel the download and left the incomplete file in the user’s storage&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Now we’ll listen to the &lt;strong&gt;&lt;em&gt;Dio&lt;/em&gt;&lt;/strong&gt; provided callback “&lt;strong&gt;&lt;em&gt;onReceiveProgress&lt;/em&gt;&lt;/strong&gt;” to update our &lt;strong&gt;notifier&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="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;dio&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;download&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="n"&gt;fileUrl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;localRouteToSaveFileStr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nl"&gt;options:&lt;/span&gt; &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nl"&gt;cancelToken:&lt;/span&gt; &lt;span class="n"&gt;cancelToken&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nl"&gt;deleteOnError:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nl"&gt;onReceiveProgress:&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;received&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;total&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;_onReceiveProgress&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;received&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;fileOriginSize&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;
  
  
  &lt;strong&gt;Take a look at the example repo in GitHub:&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/rlazom/resumeDownload"&gt;https://github.com/rlazom/resumeDownload&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If this was helpful to you please clap your hands a bit and follow me for more content. 👏👏👏&lt;/p&gt;

</description>
      <category>flutter</category>
      <category>downloads</category>
      <category>plugins</category>
      <category>dart</category>
    </item>
    <item>
      <title>Compass Heading with AnimatedRotation in Flutter</title>
      <dc:creator>Rene Lazo Mendez</dc:creator>
      <pubDate>Thu, 09 Jun 2022 04:13:48 +0000</pubDate>
      <link>https://dev.to/rlazom/compass-heading-with-animatedrotation-in-flutter-3ji2</link>
      <guid>https://dev.to/rlazom/compass-heading-with-animatedrotation-in-flutter-3ji2</guid>
      <description>&lt;h2&gt;
  
  
  Create a smooth angle transition for the users in your map application
&lt;/h2&gt;

&lt;p&gt;So, I'm working on a project that involves a map. One of the requirements was to update not only the position, but also were the user points to.&lt;/p&gt;

&lt;p&gt;To do this, I integrated the following plugins into the app:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://pub.dev/packages/flutter_compass"&gt;flutter_compass&lt;/a&gt; - A Flutter compass. The heading varies from 0-360, 0 being north.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://pub.dev/packages/flutter_map"&gt;flutter_map&lt;/a&gt; - A versatile mapping package for Flutter, based off leaflet.js, that's simple and easy to learn, yet completely customizable and configurable.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For full documentation on the flutter_compass plugin, see the &lt;a href="https://pub.dev/packages/flutter_compass/example"&gt;the example page&lt;/a&gt; on &lt;a href="https://pub.dev"&gt;pub.dev&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Now, to get the continuous changes in the user's heading we need to subscribe to the API provided by the &lt;em&gt;flutter_compass&lt;/em&gt; plugin:&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;double&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="n"&gt;userHeading&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="n"&gt;FlutterCompass&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;events&lt;/span&gt;&lt;span class="o"&gt;?.&lt;/span&gt;&lt;span class="na"&gt;listen&lt;/span&gt;&lt;span class="o"&gt;((&lt;/span&gt;&lt;span class="n"&gt;CompassEvent&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;userHeading&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;heading&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;If &lt;em&gt;direction&lt;/em&gt; is &lt;em&gt;null&lt;/em&gt; this means the client does not have the compass sensor on their device, &lt;strong&gt;and this scenario must be handled so as not to have exceptions in the execution of our app.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;To expose this &lt;em&gt;direction&lt;/em&gt; value, you could have several approaches:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;StreamBuilder&lt;/li&gt;
&lt;li&gt;Provider&lt;/li&gt;
&lt;li&gt;ValueNotifier&lt;/li&gt;
&lt;li&gt;etc.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But this is not the main topic, so just use your preferred one ;)&lt;/p&gt;

&lt;p&gt;For the widget, the plugin's example suggest us to use &lt;em&gt;Transform.rotate&lt;/em&gt; as follows:&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;Transform&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;rotate&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
  &lt;span class="nl"&gt;angle:&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;direction&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;math&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;pi&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;180&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="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt;
  &lt;span class="nl"&gt;child:&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;asset&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'assets/compass.jpg'&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 though it works, I have found another way to make the angle changes in a smooth way.&lt;/p&gt;

&lt;h3&gt;
  
  
  Which other option do we have???
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://api.flutter.dev/flutter/widgets/AnimatedRotation-class.html"&gt;&lt;strong&gt;AnimatedRotation&lt;/strong&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Animated version of Transform.rotate which automatically transitions the child's rotation over a given duration whenever the given rotation changes.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;But this widget requires a &lt;strong&gt;turn&lt;/strong&gt; value to check against its previous value and then animate the transition of the rotation, left to right (if the value increases) or right to left (if the value decreases).&lt;/p&gt;
&lt;h3&gt;
  
  
  Transform the angle into turns
&lt;/h3&gt;

&lt;p&gt;Ok cool, this is easy right? Simply divide the direction / 360 to get a value based on where the user is pointing.&lt;/p&gt;

&lt;p&gt;But now we will face the first BIG issue:&lt;br&gt;
The compass will misbehave in two scenarios:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If the user's rotation it's from 1 degree to 360.&lt;/li&gt;
&lt;li&gt;If the user's rotation it's from 360 degrees to 1.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  This is the tricky part
&lt;/h3&gt;

&lt;p&gt;Because we will need to do some math to just get the variation of the angle and then get the expected behavior.&lt;/p&gt;

&lt;p&gt;Lets upgrade our listener function 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;double&lt;/span&gt; &lt;span class="n"&gt;turns&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="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;prevValue&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="n"&gt;FlutterCompass&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;events&lt;/span&gt;&lt;span class="o"&gt;?.&lt;/span&gt;&lt;span class="na"&gt;listen&lt;/span&gt;&lt;span class="o"&gt;((&lt;/span&gt;&lt;span class="n"&gt;CompassEvent&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;)&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;?&lt;/span&gt; &lt;span class="n"&gt;direction&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;heading&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

  &lt;span class="n"&gt;direction&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;direction&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&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="mi"&gt;360&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;direction&lt;/span&gt;&lt;span class="o"&gt;):&lt;/span&gt; &lt;span class="n"&gt;direction&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;diff&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;direction&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;prevValue&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;diff&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;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;180&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;prevValue&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;direction&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;diff&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;360&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;direction&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;prevValue&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="k"&gt;else&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;diff&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;360&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;prevValue&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;direction&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="n"&gt;diff&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;diff&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="o"&gt;}&lt;/span&gt;
  &lt;span class="n"&gt;turns&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;diff&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;360&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
  &lt;span class="n"&gt;prevValue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;direction&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 now have in &lt;strong&gt;turns&lt;/strong&gt; the desire value, just the change between the last and the new angle.&lt;/p&gt;

&lt;p&gt;The widget should look 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="n"&gt;AnimatedRotation&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
  &lt;span class="nl"&gt;turns:&lt;/span&gt; &lt;span class="n"&gt;turns&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
  &lt;span class="nl"&gt;duration:&lt;/span&gt; &lt;span class="kd"&gt;const&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;milliseconds:&lt;/span&gt; &lt;span class="mi"&gt;250&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt;
  &lt;span class="nl"&gt;child:&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;Icon&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Icons&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;arrow_upward_outlined&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;I hope this helps you and saves you some time ;)&lt;/p&gt;

</description>
      <category>flutter</category>
      <category>dart</category>
      <category>sensors</category>
      <category>animation</category>
    </item>
    <item>
      <title>Easy and Dynamic Themes in Flutter</title>
      <dc:creator>Rene Lazo Mendez</dc:creator>
      <pubDate>Thu, 15 Oct 2020 05:54:03 +0000</pubDate>
      <link>https://dev.to/rlazom/easy-and-dynamic-themes-in-flutter-3ih6</link>
      <guid>https://dev.to/rlazom/easy-and-dynamic-themes-in-flutter-3ih6</guid>
      <description>&lt;h2&gt;
  
  
  Develop an application with dynamic themes has never felt easier than with &lt;a href="https://pub.dev/packages/easy_dynamic_theme"&gt;Easy Dynamic Theme&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;When I decided to add this feature in my current project I came across several ways to achieve this goal, but none of them really got all my needs covered.&lt;/p&gt;

&lt;p&gt;I was looking for a plugin (or some easy way) that would provide:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Dynamic theme&lt;/strong&gt;: On new versions of Android you can define on the system setting the mode (light / dark) of your preference, and I need my app to get this information and build the UI accordingly.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Switch between themes&lt;/strong&gt;: Some users may want to "force" his preferred theme no matter what the system says, or actually reset the theme mode to dynamic and be defined by the system.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Persist user selection&lt;/strong&gt;: Of course, this option is not negotiable.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This was what I was aiming to find, so I took all the little pieces I found and made to myself a pretty good looking hello world app, and at that point I decided to make a plugin that could make things easier to other flutter developers who want to achieve this too, as easily as I can and save them as many hours of tedious web searching as possible.&lt;/p&gt;

&lt;h2&gt;
  
  
  Enough chitchat, let's show some code
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Let's get the app configuration ready:
&lt;/h3&gt;

&lt;p&gt;All the cool magic occurs in the &lt;code&gt;main.dart&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;First, just wrap your &lt;em&gt;MyApp&lt;/em&gt; with an &lt;em&gt;EasyDynamicThemeWidget&lt;/em&gt; and add the values for the &lt;em&gt;theme&lt;/em&gt;, &lt;em&gt;darkTheme&lt;/em&gt; and &lt;em&gt;themeMode&lt;/em&gt; attributes in your &lt;strong&gt;MaterialApp&lt;/strong&gt; as follows:&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="n"&gt;runApp&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt; 
    &lt;span class="n"&gt;EasyDynamicThemeWidget&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt; 
      &lt;span class="nl"&gt;child:&lt;/span&gt; &lt;span class="n"&gt;MyApp&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;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyApp&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="n"&gt;StatelessWidget&lt;/span&gt; &lt;span class="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;title&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;'Easy Dynamic Theme'&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;MaterialApp&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;title&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; 
      &lt;span class="nl"&gt;theme:&lt;/span&gt; &lt;span class="n"&gt;ThemeData&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;light&lt;/span&gt;&lt;span class="o"&gt;(),&lt;/span&gt; 
      &lt;span class="nl"&gt;darkTheme:&lt;/span&gt; &lt;span class="n"&gt;ThemeData&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;dark&lt;/span&gt;&lt;span class="o"&gt;(),&lt;/span&gt; 
      &lt;span class="nl"&gt;themeMode:&lt;/span&gt; &lt;span class="n"&gt;EasyDynamicThemeWidget&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;of&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="na"&gt;themeMode&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; 
      &lt;span class="nl"&gt;home:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;MyHomePage&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;title&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;h4&gt;
  
  
  No way, is that it!!!??? Yes, easy as that.
&lt;/h4&gt;

&lt;h3&gt;
  
  
  How can I actually change the theme?:
&lt;/h3&gt;

&lt;p&gt;To do this, you just need to execute this from anywhere in 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="n"&gt;EasyDynamicTheme&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;of&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="na"&gt;changeTheme&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With the code above, you will toggle (starting from your &lt;em&gt;current theme&lt;/em&gt;) between the &lt;em&gt;Theme Modes&lt;/em&gt; in the following order:&lt;br&gt;
&lt;strong&gt;dynamic&lt;/strong&gt; -&amp;gt; &lt;strong&gt;light&lt;/strong&gt; -&amp;gt; &lt;strong&gt;dark&lt;/strong&gt; -&amp;gt; &lt;strong&gt;dynamic&lt;/strong&gt; -&amp;gt; ...&lt;/p&gt;

&lt;p&gt;Or, if you prefer to play yourself with it, the function have two optional parameters (&lt;strong&gt;dynamic&lt;/strong&gt; and &lt;strong&gt;dark&lt;/strong&gt;) to achieve this.&lt;/p&gt;
&lt;h3&gt;
  
  
  And if I want to get the current theme?:
&lt;/h3&gt;

&lt;p&gt;Well, in that case, you can get the current theme of your application as follows:&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;ThemeMode&lt;/span&gt; &lt;span class="n"&gt;themeMode&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;EasyDynamicTheme&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;of&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="na"&gt;themeMode&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will return one of the following values:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;ThemeMode.system&lt;/strong&gt; - Use either the light or dark theme based on what the user has selected in the system settings.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;ThemeMode.light&lt;/strong&gt; - Always use the light mode regardless of system preference.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;ThemeMode.dark&lt;/strong&gt; - Always use the dark mode (if available) regardless of system preference.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Easy peasy, don't you think? ;)&lt;/p&gt;

&lt;p&gt;Please visit my &lt;a href="https://github.com/rlazom/easy_dynamic_theme"&gt;Github Repo&lt;/a&gt; or the plugin's page at &lt;a href="https://pub.dev/packages/easy_dynamic_theme"&gt;pub.dev&lt;/a&gt; for full documentation.&lt;/p&gt;

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