<?xml version="1.0" encoding="utf-8" ?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:tt="http://teletype.in/" xmlns:opensearch="http://a9.com/-/spec/opensearch/1.1/"><title>IT KPI Dart English</title><subtitle>English alt for IT KPI Dart (Ukrainian)
https://teletype.in/@itkpi_dart</subtitle><author><name>IT KPI Dart English</name></author><id>https://teletype.in/atom/itkpi_dart_en</id><link rel="self" type="application/atom+xml" href="https://teletype.in/atom/itkpi_dart_en?offset=0"></link><link rel="alternate" type="text/html" href="https://teletype.in/@itkpi_dart_en?utm_source=teletype&amp;utm_medium=feed_atom&amp;utm_campaign=itkpi_dart_en"></link><link rel="next" type="application/rss+xml" href="https://teletype.in/atom/itkpi_dart_en?offset=10"></link><link rel="search" type="application/opensearchdescription+xml" title="Teletype" href="https://teletype.in/opensearch.xml"></link><updated>2026-04-19T21:54:50.362Z</updated><entry><id>itkpi_dart_en:Future-Completer</id><link rel="alternate" type="text/html" href="https://teletype.in/@itkpi_dart_en/Future-Completer?utm_source=teletype&amp;utm_medium=feed_atom&amp;utm_campaign=itkpi_dart_en"></link><title>Completer: Creating own Futures</title><published>2021-05-05T20:33:07.203Z</published><updated>2021-05-05T21:57:24.151Z</updated><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://teletype.in/files/58/4a/584a835e-ed09-41db-a144-b1499c925293.png"></media:thumbnail><category term="dart" label="Dart"></category><summary type="html">&lt;img src=&quot;https://teletype.in/files/85/26/85268927-d177-4d52-a5d7-d599e872137c.png&quot;&gt;Sometimes while writing your code, you may realize the interface the Future class provides is insufficient for your needs. This happens mostly when you create own libraries or controllers.</summary><content type="html">
  &lt;p&gt;Sometimes while writing your code, you may realize the interface the Future class provides is insufficient for your needs. This happens mostly when you create own libraries or controllers.&lt;/p&gt;
  &lt;p&gt;Future is a basic term to understand while coding in Dart. You can have a complete dive-in into asynchronous programming &lt;a href=&quot;https://teletype.in/@itkpi_dart/Asynchronous-programming&quot; target=&quot;_blank&quot;&gt;in a dart.dev codelab&lt;/a&gt;.&lt;/p&gt;
  &lt;p&gt;In this article we detect a Race Condition error in some asynchronous code and solve it using a Completer.&lt;/p&gt;
  &lt;blockquote&gt;This article is a translation of &lt;a href=&quot;https://teletype.in/@itkpi_dart/Future-Completer&quot; target=&quot;_blank&quot;&gt;our original article&lt;/a&gt; in Ukrainian&lt;/blockquote&gt;
  &lt;figure class=&quot;m_column&quot;&gt;
    &lt;img src=&quot;https://teletype.in/files/85/26/85268927-d177-4d52-a5d7-d599e872137c.png&quot; width=&quot;1200&quot; /&gt;
  &lt;/figure&gt;
  &lt;h2&gt;What do you mean, insufficient?&lt;/h2&gt;
  &lt;p&gt;Let&amp;#x27;s see Future&amp;#x27;s interface:&lt;/p&gt;
  &lt;pre data-lang=&quot;dart&quot;&gt;Future(FutureOr&amp;lt;T&amp;gt; computation())
// Calls computation() asynchronously, using Timer.run
Future.delayed(Duration duration, [FutureOr&amp;lt;T&amp;gt; computation()])
// Just like Future(), but execution delays
Future.error(Object error, [StackTrace? stackTrace])
// Creates Future which completes with an error
Future.microtask(FutureOr&amp;lt;T&amp;gt; computation())
// Just like Future(), but uses scheduleMicrotask
Future.sync(FutureOr&amp;lt;T&amp;gt; computation())
// Just like Future(), but function gets called synchronously
Future.value([FutureOr&amp;lt;T&amp;gt;? value])
// Creates an already completed Future with a result&lt;/pre&gt;
  &lt;p&gt;As we can see, the given interface gives ability to produce Future as a result of some different calculations, but there&amp;#x27;s no way to indicate computations which are still running.&lt;/p&gt;
  &lt;p&gt;Instead, the given interface can be used, for example, if we&amp;#x27;re implementing some interface which requires a future to be returned, while our implementation is synchronous:&lt;/p&gt;
  &lt;pre data-lang=&quot;dart&quot;&gt;import &amp;#x27;dart:io&amp;#x27;;

abstract class FileReader {
  Future&amp;lt;String&amp;gt; readFile(String name);
}

class SyncFileReader implements FileReader {
  @override
  Future&amp;lt;String&amp;gt; readFile(String name) {
    return Future(() {
      return File(name).readAsStringSync();
    });
  }
}&lt;/pre&gt;
  &lt;p&gt;Now let&amp;#x27;s consider we&amp;#x27;re creating a database controller. To work with a database, you need to connect to it. Furthermore, you need to store the established connection somewhere in the controller, since creating multiple parallel connections is ineffective.&lt;/p&gt;
  &lt;p&gt;Let&amp;#x27;s try creating such a controller with what we learned:&lt;/p&gt;
  &lt;pre data-lang=&quot;dart&quot;&gt;import &amp;#x27;package:sqflite/sqflite.dart&amp;#x27;;

class DbConnection {
  Database? _database;

  Future&amp;lt;Database&amp;gt; use() async {
    _database ??= await openDatabase(
      &amp;#x27;my.db&amp;#x27;,
      onCreate: (db, version) async {
        ...
      },
      version: 1,
    );

    return _database!;
  }
}&lt;/pre&gt;
  &lt;p&gt;This class has a &lt;code&gt;use()&lt;/code&gt; method, which:&lt;/p&gt;
  &lt;ul&gt;
    &lt;li&gt;Checks if there&amp;#x27;s an established connection stored&lt;/li&gt;
    &lt;li&gt;If there&amp;#x27;s no such connection, it creates it, saves it in the controller and returns it&lt;/li&gt;
    &lt;li&gt;If there is, it returns one&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p&gt;It seems like everything is all right, but you can find an issue in this implementation — if multiple independent parts of our code will try to access the database at the same time before the first connection was initiated, each request will receive its own connection:&lt;/p&gt;
  &lt;figure class=&quot;m_column&quot;&gt;
    &lt;iframe src=&quot;https://player.vimeo.com/video/545629171/?autoplay=false&amp;loop=false&amp;muted=false&amp;title=true&quot;&gt;&lt;/iframe&gt;
    &lt;figcaption&gt;Demonstration of what happens in this example&lt;/figcaption&gt;
  &lt;/figure&gt;
  &lt;p&gt;One more example of the problem:&lt;/p&gt;
  &lt;figure class=&quot;m_column&quot;&gt;
    &lt;iframe src=&quot;https://dartpad.dev/embed-dart.html?id=a1718d05d371054dadd3e8b76e0fee4b&amp;split=75&amp;null_safety=true&quot;&gt;&lt;/iframe&gt;
  &lt;/figure&gt;
  &lt;p&gt;Let&amp;#x27;s see it in detail:&lt;/p&gt;
  &lt;ul&gt;
    &lt;li&gt;&lt;code&gt;NumberHolder&lt;/code&gt; class must receive the value from the &lt;code&gt;asyncNumberGet()&lt;/code&gt; just once, after what the value must be stored to be returned every next time&lt;/li&gt;
    &lt;li&gt; &lt;code&gt;asyncNumberGet()&lt;/code&gt; increments its value after each call&lt;/li&gt;
    &lt;li&gt;In &lt;code&gt;main()&lt;/code&gt;:&lt;/li&gt;
    &lt;ul&gt;
      &lt;li&gt;Starting two requests to get the number at the same time&lt;/li&gt;
      &lt;li&gt;Launching single separate request to get the number&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/ul&gt;
  &lt;p&gt;So, it seems like it has to work so:&lt;/p&gt;
  &lt;ol&gt;
    &lt;li&gt;We create a &lt;code&gt;NumbeHolder&lt;/code&gt; instance&lt;/li&gt;
    &lt;li&gt;Call 1: &lt;code&gt;NumberHolder&lt;/code&gt; class retrieves a value from the &lt;code&gt;asyncNumberGet()&lt;/code&gt; function &lt;strong&gt;just once&lt;/strong&gt; and writes the value to the &lt;code&gt;_result&lt;/code&gt; variable. Result: 1&lt;/li&gt;
    &lt;li&gt;Call 2: The &lt;code&gt;_result&lt;/code&gt; variable is not empty, returning it. Result: 1&lt;/li&gt;
    &lt;li&gt;Call 3: The &lt;code&gt;_result&lt;/code&gt; variable is not empty, returning it. Result: 1&lt;/li&gt;
  &lt;/ol&gt;
  &lt;p&gt;In conclusion, the expected result is:&lt;/p&gt;
  &lt;pre&gt;[1, 1]
1&lt;/pre&gt;
  &lt;p&gt;But if we launch the example, we see this instead:&lt;/p&gt;
  &lt;pre&gt;[1, 2]
2&lt;/pre&gt;
  &lt;p&gt;This result happens due to a semantic error called a Race Condition: a state, when the result depends on the order the code gets executed.&lt;/p&gt;
  &lt;p&gt;In the database example we&amp;#x27;d face a resource leak due to the unused and not closed database connection.&lt;/p&gt;
  &lt;p&gt;Let&amp;#x27;s see why this happens. After checking how &lt;code&gt;Future.wait&lt;/code&gt; works, we make a conclusion that &lt;code&gt;Future.wait([task1(), task2()])&lt;/code&gt; looks something like this inside:&lt;/p&gt;
  &lt;pre data-lang=&quot;dart&quot;&gt;task1();
task2();&lt;/pre&gt;
  &lt;p&gt;It means both asynchronous tasks run concurrently, while not waiting for each other.&lt;/p&gt;
  &lt;h2&gt;Concurrency in Dart&lt;/h2&gt;
  &lt;p&gt;JavaScript developers should be already familiar with the concept of the event loop.&lt;/p&gt;
  &lt;p&gt;In short: despite the fact Dart supports true multi-threading (isolates), all the usual (synchronous and asynchronous) code gets executed in a single thread. It means all commands can run only &lt;strong&gt;one after other&lt;/strong&gt;.&lt;/p&gt;
  &lt;p&gt;At the same time the queue has one special behavior: if the interpreter reaches some asynchronous command, this command moves to the end of the queue, waiting while all the other synchronous code, located after it, runs.&lt;/p&gt;
  &lt;figure class=&quot;m_original&quot;&gt;
    &lt;img src=&quot;https://teletype.in/files/84/a0/84a07380-caff-4d03-a988-68006645d201.png&quot; width=&quot;779&quot; /&gt;
    &lt;figcaption&gt;Asynchronous code&lt;/figcaption&gt;
  &lt;/figure&gt;
  &lt;p&gt;In our example instead of &lt;code&gt;task1&lt;/code&gt; we call &lt;code&gt;number.use&lt;/code&gt;. Let&amp;#x27;s check this function again:&lt;/p&gt;
  &lt;pre data-lang=&quot;dart&quot;&gt;Future&amp;lt;int&amp;gt; use() async {
    _result ??= await asyncNumberGet();
    return _result!;
}&lt;/pre&gt;
  &lt;p&gt;Let&amp;#x27;s rewrite this function simpler and without the async-await keywords to understand its logic:&lt;/p&gt;
  &lt;pre data-lang=&quot;dart&quot;&gt;Future&amp;lt;int&amp;gt; use() {
  if (_result == null) {
    return asyncNumberGet() # Future
    .then((number) {
      _result = number;
      return number;
    });
  }
  return Future.value(_result);
}&lt;/pre&gt;
  &lt;p&gt;Now it&amp;#x27;s time to apply our knowledge about concurrency to illustrate the order of its execution in the way the Dart interpreter sees it:&lt;/p&gt;
  &lt;figure class=&quot;m_original&quot;&gt;
    &lt;img src=&quot;https://teletype.in/files/8d/dd/8dddeb0c-8033-4196-b073-71138fdc8f6d.png&quot; width=&quot;691&quot; /&gt;
  &lt;/figure&gt;
  &lt;p&gt;After this, let&amp;#x27;s call our function two times in a row as &lt;code&gt;Future.wait&lt;/code&gt; does it and sort the queue:&lt;/p&gt;
  &lt;figure class=&quot;m_original&quot;&gt;
    &lt;img src=&quot;https://teletype.in/files/69/c0/69c00dfa-8d36-4170-925f-d14317cd47de.png&quot; width=&quot;1045&quot; /&gt;
  &lt;/figure&gt;
  &lt;p&gt;Since the asynchronous code was moved, &lt;code&gt;asyncNumberGet()&lt;/code&gt; was not called yet, so &lt;code&gt;_result&lt;/code&gt; variable value wasn&amp;#x27;t set yet. Because of this the second check &lt;code&gt;_result == null&lt;/code&gt; evaluates to &lt;code&gt;true&lt;/code&gt;, so the given part of code doesn&amp;#x27;t get skipped, and in conclusion we get the &lt;code&gt;asyncNumberGet()&lt;/code&gt; to be called twice:&lt;/p&gt;
  &lt;figure class=&quot;m_original&quot;&gt;
    &lt;img src=&quot;https://teletype.in/files/fe/e1/fee13e3e-5c26-493f-b5b9-9fcc1443be26.png&quot; width=&quot;1054&quot; /&gt;
  &lt;/figure&gt;
  &lt;p&gt;Finally, the asynchronous function runs synchronously in the end of the queue.&lt;/p&gt;
  &lt;p&gt;To see how it runs, we rewrite the moved code with replacing &lt;code&gt;Future().then()&lt;/code&gt; with equal &lt;code&gt;await&lt;/code&gt; constructions so it&amp;#x27;s easier to understand it.&lt;/p&gt;
  &lt;figure class=&quot;m_original&quot;&gt;
    &lt;img src=&quot;https://teletype.in/files/1b/a3/1ba3d491-670b-40de-b040-a65d6bf9b01a.png&quot; width=&quot;945&quot; /&gt;
  &lt;/figure&gt;
  &lt;p&gt;As result, we have two &lt;code&gt;asyncNumberGet()&lt;/code&gt; calls because of the fact the condition check during the second call happens sooner than the first call ends.&lt;/p&gt;
  &lt;h2&gt;Completer to the rescue&lt;/h2&gt;
  &lt;p&gt;So, what do we do if we need to create seamless access to some cached result?&lt;/p&gt;
  &lt;p&gt;&lt;a href=&quot;https://api.dart.dev/stable/2.12.4/dart-async/Completer-class.html&quot; target=&quot;_blank&quot;&gt;Completer&lt;/a&gt; is a built-in Future controller. It can produce Futures of any kind and complete them anytime.&lt;/p&gt;
  &lt;p&gt;Completer is easy to use. A Completer instance has these methods:&lt;/p&gt;
  &lt;pre data-lang=&quot;dart&quot;&gt;complete([FutureOr&amp;lt;T&amp;gt;? value]) → void
// Completes the future with a given value
completeError(Object error, [StackTrace? stackTrace]) → void
// Completes the future with the given error&lt;/pre&gt;
  &lt;p&gt;And these properties:&lt;/p&gt;
  &lt;pre data-lang=&quot;dart&quot;&gt;future → Future&amp;lt;T&amp;gt;
// Future instance we are controlling
isCompleted → bool
// Returns true is the future is already completed&lt;/pre&gt;
  &lt;p&gt;And now, let&amp;#x27;s rewrite our example with a Completer:&lt;/p&gt;
  &lt;figure class=&quot;m_column&quot;&gt;
    &lt;iframe src=&quot;https://dartpad.dev/embed-dart.html?id=ad96d2f1296cb732cd4883f290fbfa2f&amp;split=75&amp;null_safety=true&quot;&gt;&lt;/iframe&gt;
  &lt;/figure&gt;
  &lt;p&gt;Our output this time:&lt;/p&gt;
  &lt;pre&gt;CALLED
[1, 1]
1&lt;/pre&gt;
  &lt;h2&gt;Conclusions&lt;/h2&gt;
  &lt;p&gt;Thanks to Completer, we were able to create a controlled Future instance which we can return while concurrent calculations are happening. With that, we escaped a Race Condition error.&lt;/p&gt;

</content></entry><entry><id>itkpi_dart_en:Icon-widget</id><link rel="alternate" type="text/html" href="https://teletype.in/@itkpi_dart_en/Icon-widget?utm_source=teletype&amp;utm_medium=feed_atom&amp;utm_campaign=itkpi_dart_en"></link><title>Mastering Icon: How does it work from the inside?</title><published>2021-05-05T18:35:48.315Z</published><updated>2021-05-06T08:00:06.060Z</updated><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://teletype.in/files/f8/cd/f8cd7bd4-e35e-4f7b-93a3-6c5fc9259b91.png"></media:thumbnail><category term="flutter" label="Flutter"></category><summary type="html">&lt;img src=&quot;https://teletype.in/files/1a/4e/1a4e3a14-008a-44da-a3f5-a02d2bad8b14.png&quot;&gt;In this article we will check out the Icon widget and will talk about a lifehack thanks to which values for an icon can be set dynamically: for example, to fetch it from the server.</summary><content type="html">
  &lt;p&gt;In this article we will check out the Icon widget and will talk about a lifehack thanks to which values for an icon can be set dynamically: for example, to fetch it from the server.&lt;/p&gt;
  &lt;blockquote&gt;This article is a translation of &lt;a href=&quot;/@itkpi_dart/Future-Completer&quot;&gt;our original article&lt;/a&gt; in Ukrainian&lt;/blockquote&gt;
  &lt;figure class=&quot;m_column&quot;&gt;
    &lt;img src=&quot;https://teletype.in/files/1a/4e/1a4e3a14-008a-44da-a3f5-a02d2bad8b14.png&quot; width=&quot;1200&quot; /&gt;
  &lt;/figure&gt;
  &lt;h2&gt;The Icon widget&lt;/h2&gt;
  &lt;p&gt;The Flutter&amp;#x27;s Material Framework contains a widget called Icon. This widget is used to, obviously, display icons in a Flutter app. Its difference from the Image widget lies in the fact the Icon widget is controlled by app&amp;#x27;s theme, and it integrates with its parental widgets (for example, it changes its color in IconButton widget).&lt;/p&gt;
  &lt;p&gt;Let&amp;#x27;s see arguments this widget accepts:&lt;/p&gt;
  &lt;figure class=&quot;m_custom&quot;&gt;
    &lt;img src=&quot;https://telegra.ph/file/1a2a609f85b683058e7e8.png&quot; width=&quot;515&quot; /&gt;
    &lt;figcaption&gt;Example of the Icon widget in action&lt;/figcaption&gt;
  &lt;/figure&gt;
  &lt;p&gt;The example above displays an icon from the Material Icons collection. Let&amp;#x27;s check the arguments:&lt;/p&gt;
  &lt;ul&gt;
    &lt;li&gt;&lt;strong&gt;First positional argument&lt;/strong&gt;: IconData instance. We&amp;#x27;ll talk about it below&lt;/li&gt;
    &lt;li&gt;&lt;strong&gt;Non-positional &lt;code&gt;color&lt;/code&gt; argument&lt;/strong&gt;: Color instance. Used to recolor the icon&lt;/li&gt;
    &lt;li&gt;&lt;strong&gt;Non-positional &lt;code&gt;size&lt;/code&gt; argumen&lt;/strong&gt;t: real number, icon&amp;#x27;s size in pixels&lt;/li&gt;
  &lt;/ul&gt;
  &lt;h3&gt;ImageIcon widget&lt;/h3&gt;
  &lt;p&gt;This widget accepts a raster image for straightforward use of it as an icon:&lt;/p&gt;
  &lt;figure class=&quot;m_original&quot;&gt;
    &lt;img src=&quot;https://teletype.in/files/0a/2a/0a2ad238-1a36-4922-af87-301bffa29865.png&quot; width=&quot;831&quot; /&gt;
    &lt;figcaption&gt;ImageIcon widget example&lt;/figcaption&gt;
  &lt;/figure&gt;
  &lt;p&gt;Syntax is similar to Icon, except the first argument is an instance of ImageProvider. The ImageProvider object is responsible for retrieving images for other widgets. For example, for the Image widget.&lt;/p&gt;
  &lt;p&gt;It&amp;#x27;s likely you&amp;#x27;ll never ever use ImageProvider directly, but will rely on one of the ready implementations instead:&lt;/p&gt;
  &lt;ul&gt;
    &lt;li&gt;AssetImage — retrieve an image from Flutter assets (&lt;a href=&quot;https://api.flutter.dev/flutter/painting/AssetImage-class.html&quot; target=&quot;_blank&quot;&gt;see docs about adding resources to assets&lt;/a&gt;)&lt;/li&gt;
    &lt;li&gt;NetworkImage — download an image using HTTP&lt;/li&gt;
    &lt;li&gt;FileImage — retrieve an image from a File instance&lt;/li&gt;
    &lt;li&gt;MemoryImage — build an image from a byte array in memory&lt;/li&gt;
    &lt;li&gt;ExactAssetImage — similar to AssetImage, &lt;a href=&quot;https://api.flutter.dev/flutter/painting/ExactAssetImage-class.html&quot; target=&quot;_blank&quot;&gt;see docs to find out the differences&lt;/a&gt;&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p&gt;In this example we use an image from our assets.&lt;/p&gt;
  &lt;p&gt;Need to mention, color icons are going to be reduced to monochrome ones based on alpha (transparency) channel:&lt;/p&gt;
  &lt;figure class=&quot;m_original&quot;&gt;
    &lt;img src=&quot;https://teletype.in/files/da/d9/dad98a34-fa3a-49f3-a0b5-1bd8ba353f98.png&quot; width=&quot;330&quot; /&gt;
    &lt;figcaption&gt;Colored images turn to monochrome under the ImageIcon widget, while semi-transparency is respected&lt;/figcaption&gt;
  &lt;/figure&gt;
  &lt;h3&gt;Icons and CupertinoIcons collections&lt;/h3&gt;
  &lt;p&gt;The Icons and CupertinoIcons classes are collections of icons for Material Design and iOS accordingly. Need to mention, the collections are not cross-compatible: if you are developing an app which uses Material icons on Android and Cupertino icons on iOS — you will have to set the relation be yourself or, for example, you can use the &lt;a href=&quot;https://pub.dev/packages/flutter_platform_widgets&quot; target=&quot;_blank&quot;&gt;flutter_platform_widgets&lt;/a&gt; library, which provides a limited set of icons with relations set.&lt;/p&gt;
  &lt;p&gt;The list of all the icons is provided on &lt;a href=&quot;https://fonts.google.com/icons&quot; target=&quot;_blank&quot;&gt;Material Icons page&lt;/a&gt;. Each icon is available in four styles: Regular, Rounded, Sharp, Outline. To use a needed style, you just need to add a corresponding ending:&lt;/p&gt;
  &lt;figure class=&quot;m_original&quot;&gt;
    &lt;img src=&quot;https://teletype.in/files/96/3d/963d0759-93e8-4ed0-b45f-0502ab4465fd.png&quot; width=&quot;470&quot; /&gt;
    &lt;figcaption&gt;Different icons styles use&lt;/figcaption&gt;
  &lt;/figure&gt;
  &lt;p&gt;All available Cupertino icons are listed &lt;a href=&quot;https://flutter.github.io/cupertino_icons/&quot; target=&quot;_blank&quot;&gt;on the library page&lt;/a&gt;.&lt;/p&gt;
  &lt;h2&gt;Icons and Themes&lt;/h2&gt;
  &lt;p&gt;All the Material Framework components are depending on the set theme. The theme is being defined in the MaterialApp widget using the ThemeData object in &lt;code&gt;theme&lt;/code&gt; property.&lt;/p&gt;
  &lt;p&gt;You can use the style globally for all the icons in your app using the &lt;code&gt;iconTheme&lt;/code&gt; property in ThemeData:&lt;/p&gt;
  &lt;figure class=&quot;m_original&quot;&gt;
    &lt;img src=&quot;https://teletype.in/files/ac/fd/acfd5ebc-851a-4f25-bee2-16ea09f31886.png&quot; width=&quot;537&quot; /&gt;
    &lt;figcaption&gt;Example of Theme use to set the icon style&lt;/figcaption&gt;
  &lt;/figure&gt;
  &lt;p&gt;Except from this, you can rewrite the theme directly in the widget tree by using the IconTheme widget (also, properties from the theme in MaterialApp stop working under this one):&lt;/p&gt;
  &lt;figure class=&quot;m_original&quot;&gt;
    &lt;img src=&quot;https://teletype.in/files/07/fc/07fcd815-d50b-4d80-8c58-f4285c577bcf.png&quot; width=&quot;545&quot; /&gt;
    &lt;figcaption&gt;Example of local theme override&lt;/figcaption&gt;
  &lt;/figure&gt;
  &lt;h2&gt;How vector icons work&lt;/h2&gt;
  &lt;p&gt;For vector icons, Flutter uses special icon fonts, the fonts which contain icons in place of characters. So, when you use an Icon widget, Flutter creates something like a Text widget with a specially set font. We&amp;#x27;ll make sure about this later.&lt;/p&gt;
  &lt;h3&gt;IconData type&lt;/h3&gt;
  &lt;p&gt;IconData is the container for the icon data to be drawn. Instances of this type are stored in the Icons collection: for example, &lt;code&gt;Icons.people&lt;/code&gt; is an IconData object. Let&amp;#x27;s see the constructor of this object:&lt;/p&gt;
  &lt;figure class=&quot;m_original&quot;&gt;
    &lt;img src=&quot;https://teletype.in/files/f4/a0/f4a0fe4c-d1dd-43c1-912e-9e0afa358bd1.png&quot; width=&quot;487&quot; /&gt;
    &lt;figcaption&gt;IconData constructor — that&amp;#x27;s the exact way the icons are stored in Icons and CupertinoIcons collections&lt;/figcaption&gt;
  &lt;/figure&gt;
  &lt;p&gt;&lt;strong&gt;First positional argument&lt;/strong&gt;: integer of a character code which corresponds to an icon&lt;/p&gt;
  &lt;p&gt;&lt;strong&gt;Non-positional &lt;code&gt;fontFamily&lt;/code&gt; argument&lt;/strong&gt;: font name which is used to display the icon&lt;/p&gt;
  &lt;p&gt;So, we can reintroduce this behavior using the Text widget (&lt;code&gt;\uef85&lt;/code&gt; is the character code of the icon):&lt;/p&gt;
  &lt;figure class=&quot;m_original&quot;&gt;
    &lt;img src=&quot;https://teletype.in/files/0a/8f/0a8ffaa9-e70b-465e-8224-93dc3c7a5325.png&quot; width=&quot;756&quot; /&gt;
    &lt;figcaption&gt;Icon alternative which uses Text widget&lt;/figcaption&gt;
  &lt;/figure&gt;
  &lt;p&gt;Furthermore, you can use label name instead of character code:&lt;/p&gt;
  &lt;figure class=&quot;m_original&quot;&gt;
    &lt;img src=&quot;https://teletype.in/files/1f/67/1f6747b1-a684-42e6-a224-efe489198e0b.png&quot; width=&quot;753&quot; /&gt;
    &lt;figcaption&gt;If you replace &amp;#x27;\ue8f5&amp;#x27; to &amp;#x27;people&amp;#x27;, the widget continues to work as before&lt;/figcaption&gt;
  &lt;/figure&gt;
  &lt;p&gt;Need to mention, IconData is a constant constructor, that lets the Dart compiler to exclude unused icons.&lt;/p&gt;
  &lt;h2&gt;Dynamic icons and Material Framework integration&lt;/h2&gt;
  &lt;blockquote&gt;❗ Use the technique described below only if you really need it (to store all the icons on client side and provide a needed icon name dynamically), since this hurts the app size. Instead of using this, you could try ImageIcon together with, for example, NetworkImage.&lt;/blockquote&gt;
  &lt;p&gt;So, we make a conclusion we can use the Text widget to display the icon by its code or label. Thought, this approach has a huge downside: it doesn&amp;#x27;t integrate with the Material Framework, since Flutter treats this widget as a usual text, not an icon. So let&amp;#x27;s create own Icon class which is not constant and accepts an icon name to draw (see end of the article for the implementation).&lt;/p&gt;
  &lt;p&gt;Use:&lt;/p&gt;
  &lt;figure class=&quot;m_original&quot;&gt;
    &lt;img src=&quot;https://teletype.in/files/fc/ba/fcbaaedc-b179-4bb3-9517-e22ca5db80e4.png&quot; width=&quot;517&quot; /&gt;
    &lt;figcaption&gt;DynamicIcon use example&lt;/figcaption&gt;
  &lt;/figure&gt;
  &lt;p&gt;Warning! Due to the fact the constructor is not constant, tree shaking will fail, so the app won&amp;#x27;t compile. This behavior can be disabled by the &lt;code&gt;--no-tree-shake-icons&lt;/code&gt; build flag.&lt;/p&gt;
  &lt;h3&gt;Implementation&lt;/h3&gt;
  &lt;figure class=&quot;m_column&quot;&gt;
    &lt;iframe src=&quot;https://dartpad.dev/embed-flutter.html?id=cff07341614d667d7ef9e482524c5df4&amp;split=75&amp;null_safety=true&quot;&gt;&lt;/iframe&gt;
  &lt;/figure&gt;

</content></entry></feed>