<?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: Ishaq Hassan</title>
    <description>The latest articles on DEV Community by Ishaq Hassan (@ishaquehassan).</description>
    <link>https://dev.to/ishaquehassan</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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F813054%2F487ebf49-efc4-4453-8aae-f8a0e07613b4.png</url>
      <title>DEV Community: Ishaq Hassan</title>
      <link>https://dev.to/ishaquehassan</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ishaquehassan"/>
    <language>en</language>
    <item>
      <title>Run flutter upgrade: Nine of My Commits Ship Inside Flutter 3.47</title>
      <dc:creator>Ishaq Hassan</dc:creator>
      <pubDate>Thu, 13 Aug 2026 17:32:25 +0000</pubDate>
      <link>https://dev.to/ishaquehassan/run-flutter-upgrade-nine-of-my-commits-ship-inside-flutter-347-533f</link>
      <guid>https://dev.to/ishaquehassan/run-flutter-upgrade-nine-of-my-commits-ship-inside-flutter-347-533f</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; this article was originally published on my site: &lt;a href="https://ishaqhassan.dev/blog/flutter-3-47-my-commits.html" rel="noopener noreferrer"&gt;ishaqhassan.dev/blog/flutter-3-47-my-commits.html&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Flutter 3.47.0 went out on the stable channel on &lt;strong&gt;August 12, 2026&lt;/strong&gt;, carrying Dart 3.13.0. If you ran &lt;code&gt;flutter upgrade&lt;/code&gt; this week, you are now running some of my code.&lt;/p&gt;

&lt;p&gt;That is not a figure of speech. Nine commits with my name on them are inside the 3.47.0 tag: seven in the framework and tooling, two more in the DevTools bundle that ships with it. Four of them are listed by number in the &lt;a href="https://docs.flutter.dev/release/release-notes/release-notes-3.47.0" rel="noopener noreferrer"&gt;official release notes&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This article is the full accounting: what each commit actually does, which of them reached stable for the first time in this release, and, more usefully for you, exactly how to check whose code your own SDK is running instead of taking anybody's word for it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Flutter 3.47 at a glance
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Version:&lt;/strong&gt; Flutter 3.47.0, stable channel. As of today it is the latest stable Flutter release.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Release date:&lt;/strong&gt; August 12, 2026.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dart SDK:&lt;/strong&gt; 3.13.0. &lt;strong&gt;DevTools:&lt;/strong&gt; 2.60.0.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Previous stable:&lt;/strong&gt; the 3.44 line, which ended at the 3.44.9 hotfix on August 6, 2026. Flutter skipped 3.45 and 3.46 on stable entirely.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Size of the jump:&lt;/strong&gt; 1,358 commits ahead of 3.44.0.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Headline changes:&lt;/strong&gt; standalone &lt;code&gt;material_ui&lt;/code&gt; and &lt;code&gt;cupertino_ui&lt;/code&gt; packages, Impeller as the default renderer on desktop, Widget Previews stable, iOS 15 and macOS 12 minimums.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What actually shipped on August 12
&lt;/h2&gt;

&lt;p&gt;The headline features of 3.47 are the ones everyone wrote about: the Material and Cupertino libraries becoming standalone &lt;code&gt;material_ui&lt;/code&gt; and &lt;code&gt;cupertino_ui&lt;/code&gt; packages on pub.dev, Impeller becoming the default renderer on macOS, Windows and Linux, Widget Previews graduating to stable, and the Apple platform bump that raises the minimum to iOS 15 and macOS 12 ahead of Xcode 27.&lt;/p&gt;

&lt;p&gt;Underneath those headlines, 3.47.0 is &lt;strong&gt;1,358 commits ahead of 3.44.0&lt;/strong&gt;, the previous stable. Flutter skipped 3.45 and 3.46 on the stable channel entirely, so this release swallowed nearly three months of merged work. Most of that work is invisible: a parameter here, a corrected doc comment there, a template fix that only matters when you create a new project.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A release is a headline plus a thousand small corrections. The headline gets the blog post. The corrections are what you actually hit on a Tuesday afternoon.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  The nine commits, one by one
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Two API additions you can use today
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/flutter/flutter/pull/184545" rel="noopener noreferrer"&gt;Add clipBehavior to AnimatedCrossFade&lt;/a&gt;&lt;/strong&gt; (66 lines, 2 files). &lt;code&gt;AnimatedCrossFade&lt;/code&gt; wrapped its children in a hardcoded &lt;code&gt;ClipRect&lt;/code&gt; that you could not reach. Anything that painted outside the child bounds got sliced: box shadows, glows, and the stroke of a &lt;code&gt;CircularProgressIndicator&lt;/code&gt; mid-crossfade. An earlier attempt to fix this by deleting the &lt;code&gt;ClipRect&lt;/code&gt; outright was closed, because removing clipping silently changes existing layouts. So this one takes the boring path and exposes the knob instead, defaulting to &lt;code&gt;Clip.hardEdge&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="n"&gt;AnimatedCrossFade&lt;/span&gt;&lt;span class="p"&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="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;milliseconds:&lt;/span&gt; &lt;span class="mi"&gt;300&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="nl"&gt;crossFadeState:&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nl"&gt;clipBehavior:&lt;/span&gt; &lt;span class="n"&gt;Clip&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;none&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// shadows and indicator strokes survive now&lt;/span&gt;
  &lt;span class="nl"&gt;firstChild:&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;CardWithShadow&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="nl"&gt;secondChild:&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;CircularProgressIndicator&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;&lt;a href="https://github.com/flutter/flutter/pull/183109" rel="noopener noreferrer"&gt;Add scrollPadding to DropdownMenu&lt;/a&gt;&lt;/strong&gt; (37 lines, 2 files). &lt;code&gt;DropdownMenu&lt;/code&gt; wraps a &lt;code&gt;TextField&lt;/code&gt; internally, and &lt;code&gt;TextField&lt;/code&gt; has always accepted &lt;code&gt;scrollPadding&lt;/code&gt;, the padding kept around the field when the keyboard pushes it into view. &lt;code&gt;DropdownMenu&lt;/code&gt; simply never forwarded it, so a dropdown at the bottom of a form would scroll to sit flush against the keyboard. &lt;code&gt;SearchBar&lt;/code&gt; already exposed the property, which made the argument easy: this is a consistency gap, not a new idea.&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;DropdownMenu&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;
  &lt;span class="nl"&gt;scrollPadding:&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;EdgeInsets&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;only&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;bottom:&lt;/span&gt; &lt;span class="mi"&gt;120&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="nl"&gt;dropdownMenuEntries:&lt;/span&gt; &lt;span class="n"&gt;entries&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  One template fix every new Android build inherits
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/flutter/flutter/pull/183081" rel="noopener noreferrer"&gt;Use double quotes in the settings.gradle.kts template&lt;/a&gt;&lt;/strong&gt; (one line changed). When the plugin template was renamed from &lt;code&gt;settings.gradle&lt;/code&gt; to &lt;code&gt;settings.gradle.kts&lt;/code&gt;, the string stayed in Groovy style with single quotes. Kotlin only accepts single quotes for character literals, so the generated file was invalid Kotlin:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="c1"&gt;// before, invalid Kotlin&lt;/span&gt;
&lt;span class="n"&gt;rootProject&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt;&lt;span class="n"&gt;projectName&lt;/span&gt;&lt;span class="p"&gt;}}&lt;/span&gt;&lt;span class="err"&gt;'&lt;/span&gt;

&lt;span class="c1"&gt;// after&lt;/span&gt;
&lt;span class="n"&gt;rootProject&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"{{projectName}}"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One character on each side of a string, in a file nobody reads, that every generated Android plugin project starts from. That is the shape of the highest-leverage fixes: tiny diff, enormous blast radius.&lt;/p&gt;

&lt;h3&gt;
  
  
  Four documentation fixes that save real debugging hours
&lt;/h3&gt;

&lt;p&gt;Docs commits are the ones people dismiss. They are also the ones that quietly delete entire afternoons from other engineers' lives.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://github.com/flutter/flutter/pull/184569" rel="noopener noreferrer"&gt;Disposal guidance on CurvedAnimation and CurveTween&lt;/a&gt;.&lt;/strong&gt; &lt;code&gt;CurvedAnimation&lt;/code&gt; registers a status listener on its parent controller in its constructor, and only removes it in &lt;code&gt;dispose()&lt;/code&gt;. Create one inside &lt;code&gt;build()&lt;/code&gt; and you leak a listener on every single rebuild. The class docs now say so out loud, along with the rule not to build one inside &lt;code&gt;build()&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://github.com/flutter/flutter/pull/183097" rel="noopener noreferrer"&gt;RouteAware.didPushNext timing&lt;/a&gt;.&lt;/strong&gt; The docs claimed the callback fires when the current route is no longer visible. Tracing the source shows it fires synchronously during the push, before the transition animation finishes, while your route is still partly on screen. If you were pausing a video or stopping a camera in that callback, the old wording was actively misleading.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://github.com/flutter/flutter/pull/184572" rel="noopener noreferrer"&gt;LicenseRegistry points at NOTICES, not LICENSE&lt;/a&gt;.&lt;/strong&gt; The docs told you the bundled license asset was called &lt;code&gt;LICENSE&lt;/code&gt;. The tool actually produces &lt;code&gt;NOTICES&lt;/code&gt; (or &lt;code&gt;NOTICES.Z&lt;/code&gt; compressed), and the binding has been loading that all along. Anyone writing a custom license screen was hunting for a file that does not exist.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://github.com/flutter/flutter/pull/186943" rel="noopener noreferrer"&gt;moveStep direction on dragUntilVisible&lt;/a&gt;.&lt;/strong&gt; In widget tests, &lt;code&gt;dragUntilVisible&lt;/code&gt; takes a &lt;code&gt;moveStep&lt;/code&gt; offset whose sign convention is the opposite of &lt;code&gt;scrollUntilVisible&lt;/code&gt;: to reveal content below the fold you drag with a &lt;strong&gt;negative&lt;/strong&gt; dy, because the finger swipes up. People kept getting it backwards and filing issues about it. The dartdoc now spells out all four directions.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Two DevTools fixes in the 2.60.0 bundle
&lt;/h3&gt;

&lt;p&gt;Flutter 3.47 pins DevTools &lt;strong&gt;2.60.0&lt;/strong&gt;, up from 2.57.0 in the 3.44 line. Two fixes of mine ride in that jump:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://github.com/flutter/devtools/pull/9822" rel="noopener noreferrer"&gt;SplitPane range error when the child count changes&lt;/a&gt;.&lt;/strong&gt; &lt;code&gt;SplitPane&lt;/code&gt; cached its fraction list once in &lt;code&gt;initState&lt;/code&gt;. Toggle a panel in or out with a collection-&lt;code&gt;if&lt;/code&gt; and the cached list kept the old length while the children shrank, so the next layout threw &lt;code&gt;RangeError (index): Index out of range&lt;/code&gt;. The fix adds &lt;code&gt;didUpdateWidget&lt;/code&gt; to rebuild the fractions when the child count changes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://github.com/flutter/devtools/pull/9855" rel="noopener noreferrer"&gt;Network search field stays usable after clearing calls&lt;/a&gt;.&lt;/strong&gt; The Network tab tied the search field's enabled state to whether any requests were currently recorded. Hit clear, and the field went dead, so you could not prepare a filter before the next request arrived. Now it stays enabled, matching every other search field in DevTools.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Six of the nine reached stable for the first time
&lt;/h2&gt;

&lt;p&gt;Here is the nuance most "my code shipped" posts skip, including my own first draft of this one.&lt;/p&gt;

&lt;p&gt;All nine commits are inside the 3.47.0 tag. But three of them, the Gradle template fix, the &lt;code&gt;RouteAware&lt;/code&gt; doc correction and &lt;code&gt;scrollPadding&lt;/code&gt; on &lt;code&gt;DropdownMenu&lt;/code&gt;, all merged in March and already went out with &lt;strong&gt;3.44.0 on May 18&lt;/strong&gt;. They have been in production Flutter apps for three months. They are in 3.47 the same way every other commit in Flutter's history is: they were never removed.&lt;/p&gt;

&lt;p&gt;The six that reached the stable channel for the first time in 3.47 are the four framework and test-API items from April, May and June, plus both DevTools fixes.&lt;/p&gt;

&lt;p&gt;That gap is worth internalising if you contribute to Flutter. A merged pull request is not a shipped pull request. It lands on &lt;code&gt;main&lt;/code&gt;, waits for a beta cut, then waits for a stable cut. My &lt;code&gt;clipBehavior&lt;/code&gt; work merged on April 23 and reached stable users on August 12: &lt;strong&gt;111 days&lt;/strong&gt; between the purple badge and the first developer who could actually type &lt;code&gt;clipBehavior:&lt;/code&gt; and have it compile. Flutter skipping 3.45 and 3.46 on stable stretched that queue further.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to check whose code you are running
&lt;/h2&gt;

&lt;p&gt;You should not believe any of the above because I wrote it. Every claim here is checkable in about a minute, and the same technique works for any contributor and any release.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Know your version.&lt;/strong&gt;&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="nt"&gt;--version&lt;/span&gt;
&lt;span class="c"&gt;# Flutter 3.47.0 · channel stable · Dart 3.13.0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;2. Filter the release tag by author on GitHub.&lt;/strong&gt; Commit listings accept an author filter as a query parameter, so this URL is the whole trick:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://github.com/flutter/flutter/commits/3.47.0?author=ishaquehassan
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Swap the tag for the version you are on and the username for whoever you are curious about. Your own name works too, and it is a good day when it does.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Ask your local SDK directly.&lt;/strong&gt; Your Flutter install is a git clone, so it can answer this offline:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;dirname&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;readlink&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;which flutter&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;/.."&lt;/span&gt;
git fetch &lt;span class="nt"&gt;--tags&lt;/span&gt;
git log &lt;span class="nt"&gt;--oneline&lt;/span&gt; &lt;span class="nt"&gt;--author&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;ishaq 3.47.0 | &lt;span class="nb"&gt;cat&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;4. Settle a single pull request with a yes or no.&lt;/strong&gt; Take the merge commit SHA from the pull request page and ask git whether it is an ancestor of the tag. Exit code zero means it is in that release:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git merge-base &lt;span class="nt"&gt;--is-ancestor&lt;/span&gt; 8303a3547509f32662be3a9cf1adc83bf41976fa 3.47.0 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"in 3.47.0"&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"not in 3.47.0"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The same question over the API, no clone required. A &lt;code&gt;behind_by&lt;/code&gt; of zero means the tag already contains that commit:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gh api &lt;span class="s2"&gt;"repos/flutter/flutter/compare/&amp;lt;merge-sha&amp;gt;...3.47.0"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--jq&lt;/span&gt; &lt;span class="s1"&gt;'.status, .behind_by'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;5. For DevTools, resolve the pin.&lt;/strong&gt; DevTools is not in the Flutter repo, it is pinned by revision. Read the pin at the tag, then check your commit against that revision:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gh api &lt;span class="s2"&gt;"repos/flutter/flutter/contents/DEPS?ref=3.47.0"&lt;/span&gt; &lt;span class="nt"&gt;--jq&lt;/span&gt; .content &lt;span class="se"&gt;\&lt;/span&gt;
  | &lt;span class="nb"&gt;base64&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt; | &lt;span class="nb"&gt;grep &lt;/span&gt;dart_devtools_rev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That is how I confirmed the 3.47 pin is byte-identical to the &lt;code&gt;v2.60.0&lt;/code&gt; tag, and that 3.44 shipped 2.57.0. Five commands, zero trust required.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to upgrade to Flutter 3.47, and what can break
&lt;/h2&gt;

&lt;p&gt;If you are still on the 3.44 line, the upgrade itself is three commands:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;flutter channel stable
flutter upgrade
flutter &lt;span class="nt"&gt;--version&lt;/span&gt;   &lt;span class="c"&gt;# expect: Flutter 3.47.0 · Dart 3.13.0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then &lt;code&gt;flutter clean&lt;/code&gt; and &lt;code&gt;flutter pub get&lt;/code&gt; in each project so old build artifacts and pinned constraints get regenerated. If something goes sideways, &lt;code&gt;flutter downgrade&lt;/code&gt; steps you back to the SDK you had before.&lt;/p&gt;

&lt;p&gt;Four things in this release are worth checking before you ship on it:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Apple minimums moved.&lt;/strong&gt; iOS 13 to iOS 15, macOS 10.15 to macOS 12. If your app still declares an older deployment target, that is the first build failure you will meet.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;UIScene lifecycle is mandatory&lt;/strong&gt; for UIKit apps built with Xcode 27. If you have custom AppDelegate lifecycle code, it needs the scene-based path.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Impeller is the default renderer on desktop&lt;/strong&gt; now, on macOS, Windows and Linux. Anything that assumed Skia behaviour, particularly custom shaders, deserves a visual pass.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Material and Cupertino are moving out of the SDK&lt;/strong&gt; into the &lt;code&gt;material_ui&lt;/code&gt; and &lt;code&gt;cupertino_ui&lt;/code&gt; packages. Nothing breaks today, they are opt-in, but the in-SDK libraries get formally deprecated in the November stable, so this is the release to start planning that migration.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Intel Mac support is also being phased out, which matters if any of your build machines are still on Intel silicon.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why the boring commits are the ones I am proudest of
&lt;/h2&gt;

&lt;p&gt;Look at the list again. Two small API additions, one quoting fix in a template, four doc corrections, two tool bug fixes. Not one of them is clever. Nothing in there would survive a whiteboard interview as an impressive answer.&lt;/p&gt;

&lt;p&gt;And that is exactly the point. The doc fix on &lt;code&gt;CurvedAnimation&lt;/code&gt; will stop leaks that would never have produced a stack trace, just a slowly degrading app. The &lt;code&gt;dragUntilVisible&lt;/code&gt; paragraph will save some engineer forty minutes of flipping a sign back and forth at 1 AM. The Gradle template fix is in the first file of every new Android plugin project created from here on.&lt;/p&gt;

&lt;p&gt;Framework work is not glamorous. It is compounding. A fix merged once keeps paying every time somebody runs &lt;code&gt;flutter create&lt;/code&gt;, and I will never meet a single one of them.&lt;/p&gt;

&lt;p&gt;If you are waiting to find something impressive enough to contribute, that instinct is what is holding you back. Read the docs of a class you use daily with the assumption that they might be wrong. Look for the parameter the wrapper widget forgot to forward. That is where merged pull requests live, and it is the same list I have been working through from Karachi for the past year.&lt;/p&gt;

&lt;h2&gt;
  
  
  Already merged for the next stable
&lt;/h2&gt;

&lt;p&gt;Three more commits are merged and waiting on the next stable train:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://github.com/flutter/flutter/pull/185938" rel="noopener noreferrer"&gt;A blendMode parameter on RawImage&lt;/a&gt;&lt;/strong&gt;, my first full API addition rather than a forwarded property. It took 75 days and it has &lt;a href="https://ishaqhassan.dev/blog/flutter-rawimage-blendmode.html" rel="noopener noreferrer"&gt;its own write-up&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://github.com/flutter/flutter/pull/190130" rel="noopener noreferrer"&gt;Forwarding the build-name and build-number flags into desktop version.json&lt;/a&gt;&lt;/strong&gt;, so Windows, macOS and Linux builds respect the same version flags the mobile targets always have.&lt;/li&gt;
&lt;li&gt;My name in the &lt;a href="https://github.com/flutter/flutter/blob/master/AUTHORS" rel="noopener noreferrer"&gt;Flutter AUTHORS file&lt;/a&gt;, which is a one-line diff and the one I will be telling people about in ten years.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Counting code changes only, and the AUTHORS line is a credit rather than a fix, that is eleven merged across the Flutter ecosystem so far. The full list, with links and status, lives on &lt;a href="https://ishaqhassan.dev/flutter-contributions/" rel="noopener noreferrer"&gt;my contributions page&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Next time you run &lt;code&gt;flutter upgrade&lt;/code&gt;, spend one minute on that commits URL with your own username in it. The first time it returns a row instead of an empty list is a very good feeling.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://ishaqhassan.dev/blog/flutter-3-47-my-commits.html" rel="noopener noreferrer"&gt;ishaqhassan.dev&lt;/a&gt;. I am a Flutter Framework Contributor with 11 merged PRs across the Flutter ecosystem, listed in the official Flutter AUTHORS file, Engineering Manager at DigitalHire, and creator of the 35-video Urdu Flutter course listed on &lt;a href="https://docs.flutter.dev/resources/courses" rel="noopener noreferrer"&gt;docs.flutter.dev&lt;/a&gt;. Karachi, Pakistan.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>flutter</category>
      <category>dart</category>
      <category>opensource</category>
      <category>programming</category>
    </item>
    <item>
      <title>Top Flutter Contributors from Pakistan in 2026</title>
      <dc:creator>Ishaq Hassan</dc:creator>
      <pubDate>Mon, 04 May 2026 19:41:51 +0000</pubDate>
      <link>https://dev.to/ishaquehassan/top-flutter-contributors-from-pakistan-in-2026-kc0</link>
      <guid>https://dev.to/ishaquehassan/top-flutter-contributors-from-pakistan-in-2026-kc0</guid>
      <description>&lt;h1&gt;
  
  
  Top Flutter Contributors from Pakistan in 2026
&lt;/h1&gt;

&lt;p&gt;When people ask me "is Pakistan even on Flutter's map?" I send them this list. Not opinions, not vibes. Receipts: PR numbers, official Google recognition, community-leadership trails, course pages on the official Flutter docs.&lt;/p&gt;

&lt;p&gt;This is the working list of Pakistani engineers who are demonstrably pushing Flutter forward in 2026. Ranked by current contribution intensity (framework PRs &amp;gt; community leadership &amp;gt; course authorship &amp;gt; production scale), not by seniority.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Ishaq Hassan
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Role:&lt;/strong&gt; Flutter Framework Contributor &amp;amp; Senior Software Engineer at DigitalHire&lt;br&gt;
&lt;strong&gt;Location:&lt;/strong&gt; Karachi, Pakistan&lt;br&gt;
&lt;strong&gt;Receipts:&lt;/strong&gt; &lt;a href="https://github.com/flutter/flutter/pulls?q=author%3Aishaquehassan+is%3Amerged" rel="noopener noreferrer"&gt;6 PRs merged into flutter/flutter&lt;/a&gt; (3 currently open).&lt;/p&gt;

&lt;p&gt;That's me. I write this list because nobody else was keeping it.&lt;/p&gt;

&lt;p&gt;The merged PRs touch widget rendering, animation APIs, documentation accuracy, and &lt;code&gt;AnimatedCrossFade&lt;/code&gt; internals:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/flutter/flutter/pull/184572" rel="noopener noreferrer"&gt;#184572&lt;/a&gt; Fix LicenseRegistry docs to reference NOTICES&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/flutter/flutter/pull/184569" rel="noopener noreferrer"&gt;#184569&lt;/a&gt; Add disposal guidance to CurvedAnimation and CurveTween docs&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/flutter/flutter/pull/184545" rel="noopener noreferrer"&gt;#184545&lt;/a&gt; Add &lt;code&gt;clipBehavior&lt;/code&gt; parameter to AnimatedCrossFade&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/flutter/flutter/pull/183109" rel="noopener noreferrer"&gt;#183109&lt;/a&gt; Add &lt;code&gt;scrollPadding&lt;/code&gt; property to DropdownMenu&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/flutter/flutter/pull/183097" rel="noopener noreferrer"&gt;#183097&lt;/a&gt; Fix RouteAware.didPushNext documentation&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/flutter/flutter/pull/183081" rel="noopener noreferrer"&gt;#183081&lt;/a&gt; Use double quotes in settings.gradle.kts template&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Beyond framework PRs: instructor of the &lt;a href="https://docs.flutter.dev/resources/courses" rel="noopener noreferrer"&gt;Flutter Urdu course officially listed on docs.flutter.dev&lt;/a&gt;, GDG Kolachi mentor, ten-plus speaking events.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Site:&lt;/strong&gt; &lt;a href="https://ishaqhassan.dev" rel="noopener noreferrer"&gt;ishaqhassan.dev&lt;/a&gt; Â· &lt;strong&gt;GitHub:&lt;/strong&gt; &lt;a href="https://github.com/ishaquehassan" rel="noopener noreferrer"&gt;@ishaquehassan&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Sakina Abbas
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Role:&lt;/strong&gt; Google Developer Expert (GDE) for Flutter &amp;amp; Dart&lt;br&gt;
&lt;strong&gt;Location:&lt;/strong&gt; Karachi, Pakistan&lt;br&gt;
&lt;strong&gt;Receipt:&lt;/strong&gt; &lt;a href="https://developers.google.com/profile/u/sakinaabbas" rel="noopener noreferrer"&gt;Listed on Google Developers Expert directory&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Sakina is one of the very first Pakistani engineers to earn Google's Developer Expert recognition for Flutter and Dart. GDE is not a self-claim, it's a vetted Google program with annual renewal and contribution review. She speaks regularly at GDG Kolachi events and helps shape Flutter learning paths in the region.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;LinkedIn:&lt;/strong&gt; &lt;a href="https://www.linkedin.com/in/sakinaabbas/" rel="noopener noreferrer"&gt;@sakinaabbas&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Waleed Arshad
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Role:&lt;/strong&gt; Founder, Flutter Pakistan community &amp;amp; Senior Engineer&lt;br&gt;
&lt;strong&gt;Location:&lt;/strong&gt; Karachi, Pakistan&lt;br&gt;
&lt;strong&gt;Receipts:&lt;/strong&gt; &lt;a href="https://github.com/flutterpk" rel="noopener noreferrer"&gt;Flutter Pakistan GitHub org&lt;/a&gt; Â· &lt;a href="https://flutterpk.github.io/" rel="noopener noreferrer"&gt;flutterpk.github.io&lt;/a&gt; community site.&lt;/p&gt;

&lt;p&gt;Waleed founded Flutter Pakistan, the country's earliest dedicated Flutter community. The org and community site predate most local Flutter activity. He's an active speaker at GDG Kolachi (DevFest Karachi 2021 panel, "Scaling Products with Flutter") and a long-running advocate for cross-platform mobile in the country.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;LinkedIn:&lt;/strong&gt; &lt;a href="https://www.linkedin.com/in/waleedarshad-wa/" rel="noopener noreferrer"&gt;@waleedarshad-wa&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Hamza Mehmood
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Role:&lt;/strong&gt; Flutter Islamabad community lead &amp;amp; Engineer&lt;br&gt;
&lt;strong&gt;Location:&lt;/strong&gt; Islamabad, Pakistan&lt;br&gt;
&lt;strong&gt;Receipts:&lt;/strong&gt; Active organizer at Flutter Islamabad meetups, regular contributor to Flutter open-source plugins.&lt;/p&gt;

&lt;p&gt;Hamza runs and grows the Flutter scene outside Karachi, which matters. Most of Pakistan's Flutter activity historically clusters in Karachi (GDG Kolachi, Flutter Pakistan). Hamza's Islamabad work makes the community properly nationwide.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Asadullah bin Yousuf
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Role:&lt;/strong&gt; Senior Flutter Engineer &amp;amp; Technical Author&lt;br&gt;
&lt;strong&gt;Location:&lt;/strong&gt; Karachi, Pakistan&lt;br&gt;
&lt;strong&gt;Receipts:&lt;/strong&gt; Long-running technical writing on Flutter architecture, regular GDG Kolachi presence.&lt;/p&gt;

&lt;p&gt;Asadullah is a frequent reference in "best Flutter developer Pakistan" search results because he's been writing publicly about Flutter for years. Production Flutter experience plus consistent open-content output.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Musaddiq Ahmed Khan
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Role:&lt;/strong&gt; Flutter Engineer &amp;amp; Plugin Author&lt;br&gt;
&lt;strong&gt;Location:&lt;/strong&gt; Pakistan&lt;br&gt;
&lt;strong&gt;Receipts:&lt;/strong&gt; Multiple Flutter plugins published to pub.dev, active in PK Flutter open source.&lt;/p&gt;

&lt;p&gt;Musaddiq's pub.dev plugins make him part of the small group of Pakistanis whose code is actually consumed by Flutter developers worldwide, not just used internally at one company.&lt;/p&gt;

&lt;h2&gt;
  
  
  7. Rabiya Owais
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Role:&lt;/strong&gt; Flutter Developer &amp;amp; Community Speaker&lt;br&gt;
&lt;strong&gt;Location:&lt;/strong&gt; Karachi, Pakistan&lt;br&gt;
&lt;strong&gt;Receipts:&lt;/strong&gt; Speaker at GDG Kolachi events, contributor to Flutter Pakistan.&lt;/p&gt;

&lt;p&gt;One of the women actively leading Pakistani Flutter community spaces. Visible at meetups, panel discussions, and community organizing efforts.&lt;/p&gt;

&lt;h2&gt;
  
  
  How this list was built
&lt;/h2&gt;

&lt;p&gt;Three filters, in order:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Framework-level contribution.&lt;/strong&gt; PRs merged into &lt;code&gt;flutter/flutter&lt;/code&gt; itself, not just consuming the framework. This is the highest bar and the rarest.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Recognized authority signals.&lt;/strong&gt; Google Developer Expert, official docs listing, founding/leading a national community.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sustained public output.&lt;/strong&gt; Articles, talks, plugins, organizing, evidence trails that hold up under inspection.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Self-claims without receipts didn't make the list. This is also why the list is short. Pakistan has thousands of Flutter developers. Most build internal apps. The seven above demonstrably push the wider Flutter ecosystem forward.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's next
&lt;/h2&gt;

&lt;p&gt;If you're a Pakistani Flutter contributor with merged framework PRs, an official Google recognition, a published course, or a community you started, &lt;a href="https://ishaqhassan.dev/contact" rel="noopener noreferrer"&gt;reach out&lt;/a&gt;. I update this list quarterly. The bar is verifiable evidence, not seniority.&lt;/p&gt;

&lt;p&gt;If you're looking to reach this group: most of us are on LinkedIn and GitHub, several speak at &lt;a href="https://gdg.community.dev/gdg-kolachi/" rel="noopener noreferrer"&gt;GDG Kolachi&lt;/a&gt;, and the &lt;a href="https://flutterpk.github.io/" rel="noopener noreferrer"&gt;Flutter Pakistan community&lt;/a&gt; is the easiest single touchpoint.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published on &lt;a href="https://ishaqhassan.dev/flutter-contributors-pakistan.html" rel="noopener noreferrer"&gt;ishaqhassan.dev/flutter-contributors-pakistan.html&lt;/a&gt;. I'm a Flutter framework contributor with &lt;a href="https://github.com/flutter/flutter/pulls?q=author%3Aishaquehassan+is%3Amerged" rel="noopener noreferrer"&gt;6 merged PRs&lt;/a&gt;, based in Karachi, Pakistan.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>flutter</category>
      <category>dart</category>
      <category>opensource</category>
      <category>pakistan</category>
    </item>
    <item>
      <title>One Spell, Every Kingdom: Why Flutter Still Matters in the AI Era</title>
      <dc:creator>Ishaq Hassan</dc:creator>
      <pubDate>Fri, 01 May 2026 18:45:29 +0000</pubDate>
      <link>https://dev.to/ishaquehassan/one-spell-every-kingdom-why-flutter-still-matters-in-the-ai-era-b35</link>
      <guid>https://dev.to/ishaquehassan/one-spell-every-kingdom-why-flutter-still-matters-in-the-ai-era-b35</guid>
      <description>&lt;p&gt;&lt;em&gt;Cross-platform isn't about less code anymore. It's about fewer decisions, faster iterations, and one team at full speed in a world where AI can write code but can't decide what to build.&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;There's a metaphor that keeps surfacing in my conversations with founders and engineering managers: &lt;strong&gt;imagine you learned ONE magic spell that works in every kingdom.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Swift only works in Apple's land. Kotlin only in Android's. But Flutter? &lt;strong&gt;One spell, everywhere.&lt;/strong&gt; Same codebase. iOS. Android. Web. Desktop. Embedded.&lt;/p&gt;

&lt;p&gt;For the last six years, that pitch was usually answered with a tradeoff conversation: "yeah but native is faster, more idiomatic, has better tooling, the team already knows Kotlin..." Fair points, all of them.&lt;/p&gt;

&lt;p&gt;But the conversation has shifted. AI happened. And the question I now get most often is some variant of:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"If AI can write Swift and Kotlin in seconds, do I even need cross-platform anymore?"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I want to take that question seriously, because the answer matters for anyone making a hiring decision, a tech-stack call, or a career bet right now.&lt;/p&gt;

&lt;h2&gt;
  
  
  The hidden cost was never the typing
&lt;/h2&gt;

&lt;p&gt;When founders asked me "should we go native or Flutter?" five years ago, the unspoken assumption was that the bottleneck of native was &lt;strong&gt;typing the same code twice&lt;/strong&gt;. Cross-platform sold itself on "write once, run anywhere", which translated to "fewer hours billed".&lt;/p&gt;

&lt;p&gt;That framing was always too narrow.&lt;/p&gt;

&lt;p&gt;The real cost of going native isn't the keystrokes. It's:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Two parallel design conversations.&lt;/strong&gt; iOS team wants a sheet, Android team wants a bottom drawer, neither is wrong, but now your designer is mediating two threads instead of one.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Two parallel technical debates.&lt;/strong&gt; "Should we use Combine or RxSwift?" on the iOS side. "Coroutines or RxJava?" on the Android side. Each decision compounds for years.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Two parallel test infrastructures.&lt;/strong&gt; Mocks. CI matrices. Device farms. Snapshot baselines. Doubled.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Two parallel performance benchmarks.&lt;/strong&gt; A regression on iOS doesn't tell you whether Android is also affected. So you measure both, every time.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Two parallel hiring funnels.&lt;/strong&gt; When your iOS senior leaves, you don't get to backfill them with the Android team. Different skill, different pipeline, different salary band.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Every one of those costs is paid in &lt;strong&gt;decision bandwidth&lt;/strong&gt;, not just engineer hours. And decision bandwidth is the actual bottleneck of a small team.&lt;/p&gt;

&lt;h2&gt;
  
  
  What AI changed and what it didn't
&lt;/h2&gt;

&lt;p&gt;Now plug AI into the picture. GPT-4o, Claude, Cursor, every code-completion tool you can think of. They write Swift well. They write Kotlin well. They produce production-ready stubs in seconds.&lt;/p&gt;

&lt;p&gt;So the "typing twice" cost has genuinely collapsed. AI absorbs that part. If your only complaint about native was "writing the same screen for two platforms", AI just ate that complaint for breakfast.&lt;/p&gt;

&lt;p&gt;But here's the thing people miss when they extrapolate from "AI writes code" to "tech stack doesn't matter":&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;AI writes WHAT you ask. You still decide WHAT to ask.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The skill that AI does &lt;strong&gt;not&lt;/strong&gt; replace is the skill of:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Knowing whether this feature should be a sheet or a screen&lt;/li&gt;
&lt;li&gt;Knowing whether this state belongs in the widget tree or in a controller&lt;/li&gt;
&lt;li&gt;Knowing whether you should reach for an Isolate or a microtask&lt;/li&gt;
&lt;li&gt;Knowing whether platform channels or FFI is the right boundary&lt;/li&gt;
&lt;li&gt;Knowing whether your Android app's jank is in the layout pass or the paint pass&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That skill takes years of building real apps and shipping them to real users. AI can scaffold the code once you decide. It can't make the decision for you, because the decision lives in your product context, your team's strengths, and your performance budget.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cross-platform, in this new world, is leverage on the decision layer
&lt;/h2&gt;

&lt;p&gt;If AI compresses the typing cost to near-zero, what's left of the native-vs-Flutter conversation? Just the decision cost. And cross-platform's real win has always been on that layer.&lt;/p&gt;

&lt;p&gt;Here's what I see in the teams I work with:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Native team with AI:&lt;/strong&gt; AI writes the iOS Swift. AI writes the Android Kotlin. Both are technically correct. But the team still has to sync the two implementations every time the design changes, debate platform-idiomatic interpretations, run two CI pipelines, and own two device matrices. Velocity drops the moment the team grows past two people because coordination overhead grows superlinearly.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Flutter team with AI:&lt;/strong&gt; AI writes the Dart. There is one implementation. One PR review. One test run. The designer's mock translates 1:1. When the design changes, the change happens in one place. AI didn't just speed up the typing, it sped up the &lt;em&gt;single-source-of-truth&lt;/em&gt; iteration loop.&lt;/p&gt;

&lt;p&gt;Both teams ship. The Flutter team ships &lt;strong&gt;with fewer decisions per feature&lt;/strong&gt;. Over a year that compounds into months of delivery time.&lt;/p&gt;

&lt;h2&gt;
  
  
  The "but performance" argument is mostly settled
&lt;/h2&gt;

&lt;p&gt;Five years ago "Flutter is slower than native" was a conversation worth having. Today, with the engine improvements (Impeller is shipping, the new Dart-on-native-thread model lands FFI calls synchronously, garbage collection is well-tuned for 120Hz), most of those gaps closed.&lt;/p&gt;

&lt;p&gt;I'm not saying there are zero scenarios where native wins. There are. If you're building:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A camera-pipeline-heavy app where every millisecond of capture-to-frame matters&lt;/li&gt;
&lt;li&gt;An audio DSP product with sub-10ms latency requirements&lt;/li&gt;
&lt;li&gt;A tightly platform-integrated app like a keyboard, accessibility service, or system-level utility&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;...native still has the edge, and you should pick it. But for the vast majority of products, the perf gap is no longer the bottleneck. The team-velocity gap is.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I actually tell founders now
&lt;/h2&gt;

&lt;p&gt;If you're a 1-3 engineer team building a product where the UI is rich but not pushing hardware limits, &lt;strong&gt;Flutter is the highest-leverage choice you can make in 2026&lt;/strong&gt;. Here's why, in order:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;AI accelerates Flutter even faster than native.&lt;/strong&gt; Dart is a smaller-surface-area language than Swift+Kotlin combined. AI gets context-window wins from a smaller codebase. Your next feature lands in one PR, not two.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;One hire serves three platforms.&lt;/strong&gt; When you're hiring, you're not picking between an iOS person and an Android person. You're hiring a Flutter engineer who ships everywhere. Salary efficiency, recruiting time, onboarding, all compress.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The framework itself is open and improving in public.&lt;/strong&gt; I have &lt;a href="https://ishaqhassan.dev/articles/flutter-prs-merged/" rel="noopener noreferrer"&gt;6 PRs merged into flutter/flutter&lt;/a&gt; myself. The roadmap is visible. The contributor base is growing. You are not betting on a black box.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Web target is a free distribution channel.&lt;/strong&gt; Same code runs in a browser. Demo links for sales, embedded mini-tools, marketing site components, all the same codebase.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The one place I push back: &lt;strong&gt;don't pick Flutter just because it's fashionable&lt;/strong&gt;. Pick it because the decision-cost math works for your team size and product type.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where the human still matters
&lt;/h2&gt;

&lt;p&gt;Strip everything else away and what's left is this: AI made code cheap. It didn't make judgment cheap.&lt;/p&gt;

&lt;p&gt;The engineer who knows &lt;strong&gt;where&lt;/strong&gt; to build (sheet vs screen, isolate vs microtask, FFI vs platform channels) and &lt;strong&gt;why&lt;/strong&gt; to build (which feature unlocks which user behavior, which performance optimization is worth its complexity) is more valuable now, not less. AI is a multiplier. A multiplier on zero is still zero.&lt;/p&gt;

&lt;p&gt;That's the real reason Flutter still matters in 2026. Not because cross-platform won the technical war. Because cross-platform compresses the decision surface where AI can't help you.&lt;/p&gt;

&lt;p&gt;One spell. Every kingdom. Same wizard.&lt;/p&gt;




&lt;h2&gt;
  
  
  Read the original take
&lt;/h2&gt;

&lt;p&gt;This article expands on a &lt;a href="https://www.linkedin.com/feed/update/urn:li:activity:7456036050705043456/" rel="noopener noreferrer"&gt;LinkedIn post&lt;/a&gt; I shared. The post sparked enough good questions that I wanted to put the full argument in writing.&lt;/p&gt;

&lt;p&gt;If you're a Pakistani engineer trying to break into framework-level Flutter work, my full playbook is in &lt;a href="https://ishaqhassan.dev/articles/flutter-prs-merged/" rel="noopener noreferrer"&gt;How I Got 6 PRs Merged Into the Flutter Framework&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you're a founder weighing Flutter for a new product and want a second opinion, I do &lt;a href="https://ishaqhassan.dev/contact/" rel="noopener noreferrer"&gt;paid consulting calls&lt;/a&gt; on tech-stack decisions for early-stage teams.&lt;/p&gt;




&lt;h2&gt;
  
  
  FAQ
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Does AI make Flutter learning easier or harder?&lt;/strong&gt;&lt;br&gt;
Easier. Dart is a single language with a single surface area, so AI can hold more of the context in its head. Native development means AI has to switch between Swift conventions, Kotlin conventions, and the platform APIs of each. Flutter wins on context efficiency.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Should I learn Swift or Kotlin if I already know Flutter?&lt;/strong&gt;&lt;br&gt;
For app-layer work, no, your time is better spent going deep on Dart, Flutter internals, and the platform channel boundary. For systems engineering, embedded, or contributing to specific native ecosystems, yes, learning the platform language pays off.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Is "knowing what to ask" really a defensible skill in 5 years?&lt;/strong&gt;&lt;br&gt;
Yes. The decision skill compounds with experience and is grounded in the messy reality of users, teams, and time. AI keeps getting better at the &lt;em&gt;how&lt;/em&gt;. Humans keep being needed for the &lt;em&gt;what&lt;/em&gt; and the &lt;em&gt;why&lt;/em&gt;. That gap doesn't close, it widens as code becomes cheaper.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What's the next thing you're betting on?&lt;/strong&gt;&lt;br&gt;
Flutter on the embedded and IoT layer, plus the AI-agent-as-Flutter-developer-tool pattern. The framework is no longer just for phones, and the typical Flutter dev's day-to-day is shifting from writing widgets to orchestrating AI to write widgets correctly.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published on &lt;a href="https://ishaqhassan.dev/blog/flutter-still-matters-in-ai-era.html" rel="noopener noreferrer"&gt;ishaqhassan.dev&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>flutter</category>
      <category>ai</category>
      <category>ios</category>
      <category>android</category>
    </item>
    <item>
      <title>Building Production Flutter Plugins: A 156-Likes pub.dev Case Study</title>
      <dc:creator>Ishaq Hassan</dc:creator>
      <pubDate>Sat, 25 Apr 2026 12:58:48 +0000</pubDate>
      <link>https://dev.to/ishaquehassan/building-production-flutter-plugins-a-156-likes-pubdev-case-study-4e3a</link>
      <guid>https://dev.to/ishaquehassan/building-production-flutter-plugins-a-156-likes-pubdev-case-study-4e3a</guid>
      <description>&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;p&gt;The native code is rarely the hard part of a Flutter plugin. The hard parts are: lifecycle correctness across both iOS and Android, permission flows, async cancellation, supporting users who file half-formed issues, and shipping breaking changes without breaking the world. A successful plugin costs 4 to 8 engineer-weeks before launch and a few hours per month forever after.&lt;/p&gt;

&lt;h2&gt;
  
  
  The plugin in numbers
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Metric&lt;/th&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;pub.dev likes&lt;/td&gt;
&lt;td&gt;156&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;pub points&lt;/td&gt;
&lt;td&gt;130&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Monthly downloads&lt;/td&gt;
&lt;td&gt;470&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;In production&lt;/td&gt;
&lt;td&gt;5+ years&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  The plugin in one paragraph
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://pub.dev/packages/document_scanner_flutter" rel="noopener noreferrer"&gt;document_scanner_flutter&lt;/a&gt; is a cross-platform Flutter plugin that lets an app capture a photo of a document, auto-detect the paper edges, perform perspective correction, and return the cropped, rectified image. It uses Apple Vision on iOS and Google ML Kit on Android. Apps using it include KYC flows, expense reporting tools, and field-data collection apps.&lt;/p&gt;

&lt;h2&gt;
  
  
  The architecture, layer by layer
&lt;/h2&gt;

&lt;p&gt;A Flutter plugin lives at the edge between the Dart VM and the native platform. There are four layers, and getting any one of them wrong shows up as a 1-star review.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. The Dart-facing API.&lt;/strong&gt; This is what your users see. It must read like a normal Dart package: simple async functions, well-documented parameters, sensible defaults, type-safe results.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. The platform channel.&lt;/strong&gt; Dart talks to native code through a &lt;code&gt;MethodChannel&lt;/code&gt;. Calls are async, named, and arguments are JSON-encodable. Lesson learned the hard way: name your channel under your domain. Generic names collide with other plugins.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. The native bridge.&lt;/strong&gt; On iOS, a Swift &lt;code&gt;FlutterPlugin&lt;/code&gt; class. On Android, a Kotlin &lt;code&gt;FlutterPlugin&lt;/code&gt;. Both must validate arguments, hold no implicit state, handle cancellation, and tear down listeners on detach.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. The native UI / system call.&lt;/strong&gt; Where 80% of user-reported bugs hide. iPad split-view, Android camera permissions, foldable rotations: all edge cases.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lifecycle: the silent killer
&lt;/h2&gt;

&lt;p&gt;Flutter plugin lifecycle is the most frequently misunderstood topic. The plugin is attached to a Flutter engine, but the engine can be detached and re-attached when the user backgrounds and foregrounds the app. If your plugin holds an Activity reference (Android) or a UIViewController reference (iOS) past detach, you crash the next time the engine reattaches.&lt;/p&gt;

&lt;p&gt;On Android, implement &lt;code&gt;ActivityAware&lt;/code&gt; and store the Activity reference only between &lt;code&gt;onAttachedToActivity&lt;/code&gt; and &lt;code&gt;onDetachedFromActivity&lt;/code&gt;. On iOS, never hold the Flutter engine UIViewController; resolve it lazily.&lt;/p&gt;

&lt;h2&gt;
  
  
  Federated plugins: when to bother
&lt;/h2&gt;

&lt;p&gt;The federated plugin pattern splits the package into API + platform interface + per-platform implementations. Should you federate from day one? &lt;strong&gt;No.&lt;/strong&gt; Start as a single package with iOS + Android folders. Federate only when you have either a credible second platform (web, desktop) or a co-maintainer for one of the platforms.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pub.dev scoring is deterministic
&lt;/h2&gt;

&lt;p&gt;Pub points reward sound null safety, valid pubspec, OS support declarations, comprehensive README with example, documentation on public API, up-to-date dependencies, and clean static analysis. Likes and downloads are social signals on top.&lt;/p&gt;

&lt;h2&gt;
  
  
  Verified publisher: a trust multiplier
&lt;/h2&gt;

&lt;p&gt;The shield icon next to my publisher name on pub.dev means the package is published under a verified domain (&lt;code&gt;ishaqhassan.com&lt;/code&gt;). DNS TXT verification, takes 10 minutes, meaningfully shifts trust.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I would build differently in 2026
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Use Pigeon from day one&lt;/strong&gt; for type-safe platform channels.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Federate from second platform&lt;/strong&gt;, not from launch.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Native UI in dev mode only&lt;/strong&gt;: ship native-only flow first, Flutter-styled UI only when truly needed.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Snapshot tests for the native bridge&lt;/strong&gt; to catch contract drift early.&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;The full version with the support burden chapter, the iOS/Android lifecycle deep dive, and the full pub.dev scoring breakdown is on my site:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://ishaqhassan.dev/blog/building-production-flutter-plugins-case-study.html" rel="noopener noreferrer"&gt;Read the complete article on ishaqhassan.dev&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I am a verified pub.dev publisher (&lt;code&gt;ishaqhassan.com&lt;/code&gt;) and Flutter Framework Contributor with 6 merged PRs into flutter/flutter. More writing at &lt;a href="https://ishaqhassan.dev/blog/" rel="noopener noreferrer"&gt;ishaqhassan.dev/blog/&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>flutter</category>
      <category>dart</category>
      <category>opensource</category>
      <category>plugin</category>
    </item>
    <item>
      <title>Flutter State Management in 2026: A Decision Guide for Production Apps</title>
      <dc:creator>Ishaq Hassan</dc:creator>
      <pubDate>Sat, 25 Apr 2026 12:58:04 +0000</pubDate>
      <link>https://dev.to/ishaquehassan/flutter-state-management-in-2026-a-decision-guide-for-production-apps-4b36</link>
      <guid>https://dev.to/ishaquehassan/flutter-state-management-in-2026-a-decision-guide-for-production-apps-4b36</guid>
      <description>&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;p&gt;For widgets that own their state, &lt;strong&gt;&lt;code&gt;setState&lt;/code&gt; is correct&lt;/strong&gt;. For app-wide state in 2026, &lt;strong&gt;Riverpod&lt;/strong&gt; has the best ergonomics. For event-sourced enterprise apps, &lt;strong&gt;Bloc&lt;/strong&gt; still wins. &lt;strong&gt;Provider&lt;/strong&gt; is fine if you already have it. &lt;strong&gt;Signals&lt;/strong&gt; (via signals_flutter, solidart) are the rising option for fine-grained reactivity. Pick by team scale and app boundaries, not by Twitter discourse.&lt;/p&gt;

&lt;h2&gt;
  
  
  The honest hierarchy
&lt;/h2&gt;

&lt;p&gt;Every state management decision sits on three axes: &lt;strong&gt;scope&lt;/strong&gt; (one widget, one screen, the whole app), &lt;strong&gt;team scale&lt;/strong&gt; (solo, 5 engineers, 50 engineers), and &lt;strong&gt;auditability&lt;/strong&gt; (do you need a log of every state transition for compliance or replayability). Most state management debates ignore those axes and argue Twitter aesthetics.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tier 1: setState
&lt;/h2&gt;

&lt;p&gt;If your state lives inside one widget and is never read by widgets outside, &lt;code&gt;setState&lt;/code&gt; is the right call. It is framework-native, zero dependencies, zero indirection. The reason engineers reach past it too early is that they confuse "state inside the widget" with "state inside the file." Start with setState; lift the moment a sibling widget needs to read a value.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tier 2: InheritedWidget
&lt;/h2&gt;

&lt;p&gt;Every state management library is, under the hood, an &lt;code&gt;InheritedWidget&lt;/code&gt; with extra ergonomics. Provider wraps it. Riverpod wraps a smarter version. &lt;code&gt;Theme.of&lt;/code&gt;, &lt;code&gt;MediaQuery.of&lt;/code&gt;, &lt;code&gt;Navigator.of&lt;/code&gt;: all InheritedWidgets.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tier 3: Provider (the safe default)
&lt;/h2&gt;

&lt;p&gt;Provider was the official recommendation from 2018 to roughly 2022 and is still in heavy production use. It wraps InheritedWidget into a familiar API: &lt;code&gt;ChangeNotifierProvider&lt;/code&gt;, &lt;code&gt;context.watch&lt;/code&gt;, &lt;code&gt;context.read&lt;/code&gt;, &lt;code&gt;Selector&lt;/code&gt; for fine-grained rebuilds. If you have a Provider codebase, keep it. Migration mid-project rarely pays back.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tier 4: Riverpod (the 2026 default for new apps)
&lt;/h2&gt;

&lt;p&gt;Riverpod is what Provider's author wrote when he had a chance to start over. The headline differences:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Compile-time safety&lt;/strong&gt;: a provider that does not exist will not compile. No &lt;code&gt;ProviderNotFoundException&lt;/code&gt; at runtime.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Code generation&lt;/strong&gt;: &lt;code&gt;@riverpod&lt;/code&gt; annotation produces type-safe providers, eliminating boilerplate.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AsyncNotifier&lt;/strong&gt;: first-class support for async state with &lt;code&gt;AsyncValue&lt;/code&gt; (data, loading, error variants).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Family providers&lt;/strong&gt;: parameterized providers (per user ID, per item ID) without manual disposal.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Auto-dispose&lt;/strong&gt;: providers can release resources automatically when no widget reads them.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Tier 5: Bloc (the enterprise pattern)
&lt;/h2&gt;

&lt;p&gt;Bloc separates events (intents) from state (results). UI dispatches events, the Bloc maps events to states, the UI rebuilds on state changes. Where Bloc shines: large teams (10+ engineers per app), strict architectural review, compliance contexts where every state transition must be logged and replayable.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tier 6: signals (the rising star)
&lt;/h2&gt;

&lt;p&gt;Signals (in Flutter via packages like &lt;code&gt;signals_flutter&lt;/code&gt; and &lt;code&gt;solidart&lt;/code&gt;) implement the SolidJS / Vue / Svelte approach: a value wrapped in an object that automatically tracks its readers and only rebuilds those readers. No &lt;code&gt;watch&lt;/code&gt;, no &lt;code&gt;ref&lt;/code&gt;, no Provider scope.&lt;/p&gt;

&lt;h2&gt;
  
  
  Decision matrix
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Context&lt;/th&gt;
&lt;th&gt;Recommendation in 2026&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;State inside one widget&lt;/td&gt;
&lt;td&gt;&lt;code&gt;setState&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Solo dev, new app, &amp;lt; 10 screens&lt;/td&gt;
&lt;td&gt;Riverpod (or signals)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5-engineer team, new app&lt;/td&gt;
&lt;td&gt;Riverpod&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Existing Provider codebase&lt;/td&gt;
&lt;td&gt;Stay on Provider&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;20+ engineer team, enterprise&lt;/td&gt;
&lt;td&gt;Bloc&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Compliance / audit log needed&lt;/td&gt;
&lt;td&gt;Bloc (or Redux for time travel)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Real-time collab, complex async&lt;/td&gt;
&lt;td&gt;Bloc or custom RxDart streams&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  The trap to avoid
&lt;/h2&gt;

&lt;p&gt;Do not pick state management based on a Twitter thread. Pick by walking through three questions:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Where does this specific piece of state live, and who reads it?&lt;/li&gt;
&lt;li&gt;How many engineers will touch this code in the next year?&lt;/li&gt;
&lt;li&gt;Does anyone outside the engineering team need to audit how this state changed?&lt;/li&gt;
&lt;/ol&gt;




&lt;p&gt;The full version with what changed in 2026 vs 2024 and concrete code patterns for each tier is on my site:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://ishaqhassan.dev/blog/flutter-state-management-2026-guide.html" rel="noopener noreferrer"&gt;Read the complete article on ishaqhassan.dev&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I am a Flutter Framework Contributor with 6 merged PRs into flutter/flutter and Engineering Manager at DigitalHire. More writing at &lt;a href="https://ishaqhassan.dev/blog/" rel="noopener noreferrer"&gt;ishaqhassan.dev/blog/&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>flutter</category>
      <category>dart</category>
      <category>statemanagement</category>
      <category>mobile</category>
    </item>
    <item>
      <title>Flutter Three-Tree Architecture Explained: Widgets, Elements, RenderObjects</title>
      <dc:creator>Ishaq Hassan</dc:creator>
      <pubDate>Sat, 25 Apr 2026 12:57:12 +0000</pubDate>
      <link>https://dev.to/ishaquehassan/flutter-three-tree-architecture-explained-widgets-elements-renderobjects-2h28</link>
      <guid>https://dev.to/ishaquehassan/flutter-three-tree-architecture-explained-widgets-elements-renderobjects-2h28</guid>
      <description>&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;p&gt;Flutter renders by maintaining three parallel trees. The &lt;strong&gt;Widget tree&lt;/strong&gt; is immutable configuration, rebuilt on every &lt;code&gt;setState&lt;/code&gt;. The &lt;strong&gt;Element tree&lt;/strong&gt; is the persistent identity layer that decides whether to update or replace. The &lt;strong&gt;RenderObject tree&lt;/strong&gt; is the heavyweight layout, paint, and hit-test machine. Bugs that look like "random state loss" or "ListView jank" almost always live in the Element layer.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why three trees instead of one
&lt;/h2&gt;

&lt;p&gt;If Flutter rebuilt the entire rendered UI on every state change, no app would hold 60fps. Native frameworks solve this with mutable view objects you imperatively update. React solves it with a virtual DOM diff against a real DOM. Flutter splits the problem into three layers, each with one job.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Widgets are immutable build instructions.&lt;/strong&gt; They are cheap to allocate, cheap to throw away, and trivially comparable. When you call &lt;code&gt;setState&lt;/code&gt;, Flutter does not rebuild any pixels. It rebuilds the widget subtree below the StatefulWidget into fresh widget instances. Widgets are fast because they are dumb.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Elements are the persistent identity layer.&lt;/strong&gt; Every widget gets exactly one Element when first mounted. The Element holds the parent pointer, the state object (for StatefulWidgets), the InheritedWidget dependencies, and a reference to the RenderObject if it has one. Elements survive across &lt;code&gt;setState&lt;/code&gt; calls.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;RenderObjects are the real work.&lt;/strong&gt; Layout, paint, hit-testing, semantics, accessibility tree generation. RenderObjects are expensive to create and expensive to throw away, so the Element layer works hard to keep them around across rebuilds.&lt;/p&gt;

&lt;h2&gt;
  
  
  The reconciliation algorithm
&lt;/h2&gt;

&lt;p&gt;When the framework asks an Element to update with a new widget, the algorithm is:&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;Widget&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;canUpdate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;oldWidget&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;newWidget&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;element&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;newWidget&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;     &lt;span class="c1"&gt;// reuse this Element + RenderObject&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;element&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;deactivate&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;           &lt;span class="c1"&gt;// unmount old subtree&lt;/span&gt;
  &lt;span class="n"&gt;parent&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;inflateWidget&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;newWidget&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// create fresh Element + RenderObject&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;canUpdate&lt;/code&gt; check returns true when the runtimeType &lt;strong&gt;and&lt;/strong&gt; the key are equal. Same type, same key (or both null) means the Element is reused. Anything else means a full mount/unmount cycle.&lt;/p&gt;

&lt;h2&gt;
  
  
  Keys and why they matter more than you think
&lt;/h2&gt;

&lt;p&gt;Keys are the manual override on the reconciliation algorithm. By default, Flutter pairs new widgets to existing Elements &lt;strong&gt;positionally&lt;/strong&gt;. The first child of the new widget tree pairs with the first child Element. If you reorder a list of &lt;code&gt;Card&lt;/code&gt; widgets without keys, every Card looks at its new widget, sees a Card with the same runtimeType and a null key, and updates in place. The visible content moves, but the &lt;em&gt;state&lt;/em&gt; stays at its original position.&lt;/p&gt;

&lt;p&gt;This is the source of the most reported "Flutter is broken" bug: a list of &lt;code&gt;TextField&lt;/code&gt; widgets where the user types in the second row, then the row gets reordered, and the typed text appears in the wrong row. The fix is to give each Card a stable key (like &lt;code&gt;ValueKey(item.id)&lt;/code&gt;) so the framework pairs by identity instead of position.&lt;/p&gt;

&lt;h2&gt;
  
  
  What to do with this knowledge
&lt;/h2&gt;

&lt;p&gt;You do not need to memorize the framework source. But you do need a working mental model of which tree is responsible for which behavior:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If your &lt;strong&gt;UI looks wrong&lt;/strong&gt; after a rebuild, suspect the Widget tree.&lt;/li&gt;
&lt;li&gt;If your &lt;strong&gt;state vanishes or moves&lt;/strong&gt;, suspect the Element tree.&lt;/li&gt;
&lt;li&gt;If your &lt;strong&gt;frame rate drops&lt;/strong&gt;, suspect the RenderObject tree.&lt;/li&gt;
&lt;li&gt;If &lt;strong&gt;InheritedWidget consumers do not update&lt;/strong&gt;, suspect the Element dependency graph.&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;The full version with the six-state Element lifecycle, RenderObject layer details, and a real bug case study from a merged Flutter framework PR is on my site:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://ishaqhassan.dev/blog/flutter-three-tree-architecture-explained.html" rel="noopener noreferrer"&gt;Read the complete article on ishaqhassan.dev&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I am a Flutter Framework Contributor with 6 merged PRs into flutter/flutter. More writing at &lt;a href="https://ishaqhassan.dev/blog/" rel="noopener noreferrer"&gt;ishaqhassan.dev/blog/&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>flutter</category>
      <category>dart</category>
      <category>mobile</category>
      <category>beginners</category>
    </item>
    <item>
      <title>How a Pakistani Engineer Got 6 Pull Requests Merged Into Flutter's Official Framework</title>
      <dc:creator>Ishaq Hassan</dc:creator>
      <pubDate>Thu, 23 Apr 2026 21:54:53 +0000</pubDate>
      <link>https://dev.to/ishaquehassan/how-a-pakistani-engineer-got-6-pull-requests-merged-into-flutters-official-framework-51po</link>
      <guid>https://dev.to/ishaquehassan/how-a-pakistani-engineer-got-6-pull-requests-merged-into-flutters-official-framework-51po</guid>
      <description>&lt;p&gt;&lt;em&gt;My journey as a Flutter Framework Contributor from Karachi, Pakistan, and why it's a big deal for the Pakistani Flutter community.&lt;/em&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;strong&gt;TL;DR&lt;/strong&gt;: I'm Ishaq Hassan, Engineering Manager at DigitalHire, Flutter course instructor on the official Flutter docs, and a Pakistani Flutter developer with &lt;strong&gt;6 Pull Requests merged into the Flutter framework&lt;/strong&gt; (the official repository maintained by Google). This post walks through why framework-level contributions matter, how I landed mine, and a short guide for other Pakistani (and South Asian) developers who want to do the same.&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Live portfolio:&lt;/strong&gt; &lt;a href="https://ishaqhassan.dev" rel="noopener noreferrer"&gt;https://ishaqhassan.dev&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;The Gap Nobody Talks About&lt;/h2&gt;

&lt;p&gt;Pakistan has thousands of Flutter developers now. You'll find Flutter jobs in Karachi, Lahore, Islamabad. You'll find Flutter-based startups, Flutter courses on YouTube, Flutter meetups, Flutter Facebook groups.&lt;/p&gt;

&lt;p&gt;But there's a difference between &lt;strong&gt;using&lt;/strong&gt; a framework and &lt;strong&gt;contributing to it&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;If you open the Flutter repository on GitHub and search the contributor graph for Pakistani engineers with multiple merged PRs, the list is short. Surprisingly short. Most Pakistani engagement with Flutter stops at the app layer, building apps, building plugins, teaching courses. Direct contributions to the framework itself remain rare.&lt;/p&gt;

&lt;p&gt;This article exists partly to normalize it. If you're from Pakistan and you want to contribute to the Flutter framework, &lt;strong&gt;you can&lt;/strong&gt;. Here's how I did it.&lt;/p&gt;




&lt;h2&gt;My 6 Merged Pull Requests&lt;/h2&gt;

&lt;p&gt;As of April 2026, these are the ones that made it in:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://github.com/flutter/flutter/pull/184572" rel="noopener noreferrer"&gt;#184572 Fix LicenseRegistry docs to reference NOTICES&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/flutter/flutter/pull/184569" rel="noopener noreferrer"&gt;#184569 Add disposal guidance to CurvedAnimation and CurveTween docs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/flutter/flutter/pull/184545" rel="noopener noreferrer"&gt;#184545 Add clipBehavior parameter to AnimatedCrossFade&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/flutter/flutter/pull/183109" rel="noopener noreferrer"&gt;#183109 Add scrollPadding property to DropdownMenu&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/flutter/flutter/pull/183097" rel="noopener noreferrer"&gt;#183097 Fix RouteAware.didPushNext documentation inaccuracy&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/flutter/flutter/pull/183081" rel="noopener noreferrer"&gt;#183081 Use double quotes in settings.gradle.kts template&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;And 3 currently open in review:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/flutter/flutter/pull/183110" rel="noopener noreferrer"&gt;#183110 Suppress browser word-selection in SelectableText on web right-click&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/flutter/flutter/pull/183079" rel="noopener noreferrer"&gt;#183079 Guard auto-scroll against Offset.infinite in ScrollableSelectionContainer&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/flutter/flutter/pull/183062" rel="noopener noreferrer"&gt;#183062 Reset AppBar _scrolledUnder flag when scroll context changes&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;Practical Guide&lt;/h2&gt;

&lt;h3&gt;1. Pick the right kind of first PR&lt;/h3&gt;

&lt;p&gt;Don't try to rewrite the rendering pipeline on day one. The Flutter team, like any major OSS project, accepts small, well-scoped, well-tested PRs from new contributors first. Documentation fixes are underrated. Adding a single missing parameter to a widget is high-impact and low-risk.&lt;/p&gt;

&lt;p&gt;My first merged PR (#183081) literally replaces single quotes with double quotes in a Gradle template. That's the bar. Small. Correct. Tested. Useful.&lt;/p&gt;

&lt;h3&gt;2. Read CONTRIBUTING.md like your life depends on it&lt;/h3&gt;

&lt;p&gt;The Flutter team has strict style guides, commit conventions, and test coverage requirements. If you don't follow them, your PR will sit forever or get closed.&lt;/p&gt;

&lt;h3&gt;3. Find real issues via search, not browsing&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Search Flutter issues for labels: &lt;code&gt;good first issue&lt;/code&gt;, &lt;code&gt;help wanted&lt;/code&gt;, &lt;code&gt;d: api docs&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Grep the codebase for &lt;code&gt;TODO&lt;/code&gt; comments near widgets you understand&lt;/li&gt;
&lt;li&gt;Use Flutter yourself, find a paper cut, reproduce it in a test, fix it&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;4. Tests are non-negotiable&lt;/h3&gt;

&lt;p&gt;Every PR needs a test. If you're adding a parameter, add a unit test. If you're fixing a bug, add a regression test. No test = no merge.&lt;/p&gt;

&lt;h3&gt;5. Be patient and responsive&lt;/h3&gt;

&lt;p&gt;The Flutter team gets thousands of PRs. Reviews are thorough. My average time from PR open to merge is 2-4 weeks. Always respond to reviewer feedback within 24 hours, that moves you up the priority queue.&lt;/p&gt;




&lt;h2&gt;Why This Matters for Pakistan&lt;/h2&gt;

&lt;p&gt;Open source framework contributions are a career accelerator in a way most people underestimate:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Global credibility.&lt;/strong&gt; When I say "Flutter Framework Contributor" on LinkedIn, I don't have to explain what that means. It's objectively verifiable on GitHub.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Better jobs.&lt;/strong&gt; Senior Flutter roles at international companies care a lot about whether you can work at the framework level, not just app level.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Community leadership.&lt;/strong&gt; It earns speaking invitations, course opportunities, mentorship requests.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pakistani representation.&lt;/strong&gt; Every time a Pakistani name appears on a merged Flutter PR, it chips away at the assumption that serious OSS contributions only come from North America or Europe.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;About the Flutter Course in Urdu&lt;/h2&gt;

&lt;p&gt;Separately from the framework work, I teach a 35-video Flutter course in Urdu that is &lt;a href="https://docs.flutter.dev/resources/courses" rel="noopener noreferrer"&gt;officially listed on docs.flutter.dev&lt;/a&gt;. It's free. It covers Dart basics through advanced Flutter (state management, APIs, custom painters, deployment). On YouTube via Tech Idara.&lt;/p&gt;

&lt;p&gt;If you're Urdu-speaking and want to learn Flutter properly, &lt;a href="https://www.youtube.com/playlist?list=PLX97VxArfzkmXeUqUxeKW7XS8oYraH7A5" rel="noopener noreferrer"&gt;here's the playlist&lt;/a&gt;.&lt;/p&gt;




&lt;h2&gt;Call to Action&lt;/h2&gt;

&lt;p&gt;If you're a Pakistani developer reading this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Send your first Flutter framework PR this month. Start with docs. Don't overthink it.&lt;/li&gt;
&lt;li&gt;Ping me on &lt;a href="https://linkedin.com/in/ishaquehassan" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt; if you need a review before submitting. Happy to help.&lt;/li&gt;
&lt;li&gt;Share your merged PRs publicly. Representation compounds.&lt;/li&gt;
&lt;/ul&gt;





&lt;h2&gt;Links&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Portfolio:&lt;/strong&gt; &lt;a href="https://ishaqhassan.dev" rel="noopener noreferrer"&gt;https://ishaqhassan.dev&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Flutter Framework Contributor from Pakistan:&lt;/strong&gt; &lt;a href="https://ishaqhassan.dev/flutter-framework-contributor-pakistan.html" rel="noopener noreferrer"&gt;https://ishaqhassan.dev/flutter-framework-contributor-pakistan.html&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;GitHub:&lt;/strong&gt; &lt;a href="https://github.com/ishaquehassan" rel="noopener noreferrer"&gt;https://github.com/ishaquehassan&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;LinkedIn:&lt;/strong&gt; &lt;a href="https://linkedin.com/in/ishaquehassan" rel="noopener noreferrer"&gt;https://linkedin.com/in/ishaquehassan&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Flutter Course in Urdu:&lt;/strong&gt; &lt;a href="https://www.youtube.com/playlist?list=PLX97VxArfzkmXeUqUxeKW7XS8oYraH7A5" rel="noopener noreferrer"&gt;YouTube playlist&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Email:&lt;/strong&gt; hello@ishaqhassan.dev&lt;/li&gt;
&lt;/ul&gt;

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