CINXE.COM
Flutter architectural overview | Flutter
<!doctype html><html lang="en"><head><meta charset="utf-8"><title>Flutter architectural overview | Flutter</title><link rel="icon" href="/assets/images/branding/flutter/icon/64.png" eleventy:ignore><link rel="apple-touch-icon" href="/assets/images/branding/flutter/logo/flutter-logomark-320px.png" eleventy:ignore><meta name="viewport" content="width=device-width,initial-scale=1"><meta name="theme-color" content="#ffffff"><link rel="preconnect" href="https://fonts.googleapis.com"><link rel="preconnect" href="https://fonts.gstatic.com" crossorigin><meta name="google-site-verification" content="HFqxhSbf9YA_0rBglNLzDiWnrHiK_w4cqDh2YD2GEY4"><script>!function(e,t,a,n){e[n]=e[n]||[],e[n].push({"gtm.start":(new Date).getTime(),event:"gtm.js"});var g=t.getElementsByTagName(a)[0],m=t.createElement(a);m.async=!0,m.src="https://www.googletagmanager.com/gtm.js?id=GTM-ND4LWWZ",g.parentNode.insertBefore(m,g)}(window,document,"script","dataLayer")</script><script>!function(e,a,t,n,c,o,s){e.GoogleAnalyticsObject=c,e[c]=e[c]||function(){(e[c].q=e[c].q||[]).push(arguments)},e[c].l=1*new Date,o=a.createElement(t),s=a.getElementsByTagName(t)[0],o.async=1,o.src="//www.google-analytics.com/analytics.js",s.parentNode.insertBefore(o,s)}(window,document,"script",0,"ga"),ga("create","UA-67589403-1","auto"),ga("send","pageview")</script><meta name="description" content="A high-level overview of the architecture of Flutter, including the core principles and concepts that form its design."><meta name="twitter:card" content="summary_large_image"><meta name="twitter:site" content="@flutterdev"><meta property="og:title" content="Flutter architectural overview"><meta property="og:url" content="https://docs.flutter.dev/resources/architectural-overview"><meta property="og:description" content="A high-level overview of the architecture of Flutter, including the core principles and concepts that form its design."><meta property="og:image" content="https://docs.flutter.dev/assets/images/flutter-logo-sharing.png" eleventy:ignore><link href="https://fonts.googleapis.com/css2?family=Google+Sans:wght@400;500;700&display=swap" rel="stylesheet"><link href="https://fonts.googleapis.com/css2?family=Google+Sans+Text:wght@400;500;700&display=swap" rel="stylesheet"><link href="https://fonts.googleapis.com/css2?family=Google+Sans+Mono:wght@400;500;700&display=swap" rel="stylesheet"><link href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@24,400,0,0" rel="stylesheet"><script>window.__CALLBACKS=[]</script><link rel="stylesheet" href="/assets/css/main.css?v=4"></head><body><section id="cookie-notice"><div class="container"><p>docs.flutter.dev uses cookies from Google to deliver and enhance the quality of its services and to analyze traffic. <a href="https://policies.google.com/technologies/cookies" target="_blank" rel="noopener">Learn more</a>.</p><button id="cookie-consent" class="filled-button">OK, got it</button></div></section><noscript><iframe src="https://www.googletagmanager.com/ns.html?id=GTM-ND4LWWZ" height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript><div id="site-banner" role="alert"><p>Flutter 3.29 is here with a bouquet of performance and fidelity improvements for your apps! <a href="https://medium.com/flutter/whats-new-in-flutter-3-29-f90c380c2317">Learn more</a><br></p></div><header class="site-header"><a href="#document-title" id="skip-to-main" class="filled-button" tabindex="1">Skip to main content</a><nav class="navbar"><div id="site-switcher" class="dropdown"><button class="dropdown-button site-wordmark" aria-expanded="false" aria-controls="site-switcher-menu" aria-label="Switch between Flutter and Dart sites"><img src="/assets/images/branding/flutter/logo/default.svg" alt="Flutter logo" width="28"> <span>Flutter</span> <span class="subtype">Docs</span> <span class="material-symbols" aria-hidden="true">unfold_more</span></button><div class="dropdown-content" id="site-switcher-menu"><nav class="dropdown-menu" role="menu"><ul><li role="presentation"><a href="https://flutter.dev" class="site-wordmark" role="menuitem" title="Flutter homepage" aria-label="Go to the Flutter homepage"><img src="/assets/images/branding/flutter/logo/default.svg" alt="Flutter logo" width="28"> <span>Flutter</span></a></li><li role="presentation"><a href="https://docs.flutter.dev" class="site-wordmark current-site" role="menuitem" aria-current="true" title="Flutter docs homepage" aria-label="Go to the Flutter docs homepage"><img src="/assets/images/branding/flutter/logo/default.svg" alt="Flutter logo" width="28"> <span>Flutter</span> <span class="subtype">Docs</span></a></li><li role="presentation"><a href="https://api.flutter.dev" class="site-wordmark" role="menuitem" title="Flutter API reference" aria-label="Go to the Flutter API reference"><img src="/assets/images/branding/flutter/logo/default.svg" alt="Flutter logo" width="28"> <span>Flutter</span> <span class="subtype">API</span></a></li><li aria-hidden="true" class="dropdown-divider" role="separator"></li><li role="presentation"><a href="https://dart.dev" class="site-wordmark" role="menuitem" title="Dart homepage" aria-label="Go to the Dart homepage"><img src="/assets/images/branding/dart/logo.svg" alt="Dart logo" width="28" height="28"> <span>Dart</span></a></li><li role="presentation"><a href="https://dartpad.dev" class="site-wordmark" role="menuitem" title="DartPad playground" aria-label="Go to the DartPad playground"><img src="/assets/images/branding/dart/logo.svg" alt="Dart logo" width="28" height="28"> <span>DartPad</span></a></li><li role="presentation"><a href="https://pub.dev" class="site-wordmark" role="menuitem" title="pub.dev homepage" aria-label="Go to the pub.dev homepage"><img src="/assets/images/branding/dart/logo.svg" alt="Dart logo" width="28" height="28"> <span>pub.dev</span></a></li></ul></nav></div></div><div class="navbar-contents"><ul class="navbar-nav"><li class="nav-item"><a class="nav-link" href="https://flutter.dev">Homepage</a></li><li class="nav-item"><a class="nav-link" href="https://flutter.dev/community">Community</a></li><li class="nav-item"><a class="nav-link" href="https://pub.dev">Packages</a></li><li class="nav-item"><a class="nav-link" href="https://api.flutter.dev">API reference</a></li></ul><form action="/search/" class="site-header__search"><input class="site-header__searchfield search-field" type="search" name="q" id="q" autocomplete="off" placeholder="Search" aria-label="Search"></form><a href="/search" id="fallback-search-button" class="icon-button" aria-label="Navigate to the docs search page." title="Navigate to the docs search page."><span class="material-symbols" aria-hidden="true">search</span> </a><a id="call-to-action" class="filled-button" href="/get-started/install/">Get started</a> <button id="menu-toggle" class="icon-button" type="button" aria-controls="sidenav" aria-label="Toggle navigation" title="Toggle navigation"><span class="material-symbols" aria-hidden="true">menu</span></button></div></nav></header><div id="site-below-header"><div id="site-main-row"><div id="sidenav" class="site-sidebar"><nav><ul><li class="nav-header">Get started</li><li class="nav-item"><a class="nav-link" href="/get-started/install"><div><span>Set up Flutter</span></div></a></li><li class="nav-item"><button class="nav-link collapsed collapsible" data-toggle="collapse" data-target="#sidenav-3" role="button" aria-expanded="false" aria-controls="sidenav-3"><span>Learn Flutter</span> <span class="material-symbols expander" aria-hidden="true">expand_more</span></button><ul class="nav collapse" id="sidenav-3"><li class="nav-item"><a class="nav-link" href="/get-started/learn-flutter"><div><span>Introduction</span></div></a></li><li class="nav-item"><a class="nav-link" href="/get-started/codelab"><div><span>Write your first app</span></div></a></li><li class="nav-item"><button class="nav-link collapsible" data-toggle="collapse" data-target="#sidenav-3-3" role="button" aria-expanded="true" aria-controls="sidenav-3-3"><span>Learn the fundamentals</span> <span class="material-symbols expander" aria-hidden="true">expand_more</span></button><ul class="nav collapse show" id="sidenav-3-3"><li class="nav-item"><a class="nav-link" href="/get-started/fundamentals"><div><span>Introduction</span></div></a></li><li class="nav-item"><a class="nav-link" href="/get-started/fundamentals/dart"><div><span>Intro to Dart</span></div></a></li><li class="nav-item"><a class="nav-link" href="/get-started/fundamentals/widgets"><div><span>Widgets</span></div></a></li><li class="nav-item"><a class="nav-link" href="/get-started/fundamentals/layout"><div><span>Layout</span></div></a></li><li class="nav-item"><a class="nav-link" href="/get-started/fundamentals/state-management"><div><span>State management</span></div></a></li><li class="nav-item"><a class="nav-link" href="/get-started/fundamentals/user-input"><div><span>Handling user input</span></div></a></li><li class="nav-item"><a class="nav-link" href="/get-started/fundamentals/networking"><div><span>Networking and data</span></div></a></li><li class="nav-item"><a class="nav-link" href="/get-started/fundamentals/local-caching"><div><span>Local data and caching</span></div></a></li></ul></li><li class="nav-item"><button class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#sidenav-3-4" role="button" aria-expanded="false" aria-controls="sidenav-3-4"><span>From another platform?</span> <span class="material-symbols expander" aria-hidden="true">expand_more</span></button><ul class="nav collapse" id="sidenav-3-4"><li class="nav-item"><a class="nav-link" href="/get-started/flutter-for/android-devs"><div><span>Flutter for Android devs</span></div></a></li><li class="nav-item"><a class="nav-link" href="/get-started/flutter-for/compose-devs"><div><span>Flutter for Jetpack Compose devs</span></div></a></li><li class="nav-item"><a class="nav-link" href="/get-started/flutter-for/swiftui-devs"><div><span>Flutter for SwiftUI devs</span></div></a></li><li class="nav-item"><a class="nav-link" href="/get-started/flutter-for/uikit-devs"><div><span>Flutter for UIKit devs</span></div></a></li><li class="nav-item"><a class="nav-link" href="/get-started/flutter-for/react-native-devs"><div><span>Flutter for React Native devs</span></div></a></li><li class="nav-item"><a class="nav-link" href="/get-started/flutter-for/web-devs"><div><span>Flutter for web devs</span></div></a></li><li class="nav-item"><a class="nav-link" href="/get-started/flutter-for/xamarin-forms-devs"><div><span>Flutter for Xamarin.Forms devs</span></div></a></li><li class="nav-item"><a class="nav-link" href="/get-started/flutter-for/declarative"><div><span>Introduction to declarative UI</span></div></a></li><li class="nav-item"><a class="nav-link" href="/get-started/flutter-for/dart-swift-concurrency"><div><span>Flutter versus Swift concurrency</span></div></a></li></ul></li><div class="sidenav-divider"></div><li class="nav-item"><a class="nav-link" href="/codelabs"><div><span>Codelabs</span></div></a></li><li class="nav-item"><a class="nav-link" href="/cookbook"><div><span>Cookbook</span></div></a></li><li class="nav-item"><a class="nav-link" href="https://github.com/flutter/samples" target="_blank" rel="noopener"><div><span>Demos and samples</span><span class="material-symbols" aria-hidden="true">open_in_new</span></div></a></li></ul></li><li class="nav-item"><button class="nav-link collapsed collapsible" data-toggle="collapse" data-target="#sidenav-4" role="button" aria-expanded="false" aria-controls="sidenav-4"><span>Stay up to date</span> <span class="material-symbols expander" aria-hidden="true">expand_more</span></button><ul class="nav collapse" id="sidenav-4"><li class="nav-item"><a class="nav-link" href="/release/upgrade"><div><span>Upgrade</span></div></a></li><li class="nav-item"><a class="nav-link" href="/release/archive"><div><span>SDK archive</span></div></a></li><div class="sidenav-divider"></div><li class="nav-item"><a class="nav-link" href="/release/whats-new"><div><span>What's new</span></div></a></li><li class="nav-item"><a class="nav-link" href="/release/release-notes"><div><span>Release notes</span></div></a></li><li class="nav-item"><a class="nav-link" href="/release/breaking-changes"><div><span>Breaking changes</span></div></a></li><li class="nav-item"><a class="nav-link" href="/release/compatibility-policy"><div><span>Compatibility policy</span></div></a></li></ul></li><li class="nav-item"><button class="nav-link collapsed collapsible" data-toggle="collapse" data-target="#sidenav-5" role="button" aria-expanded="false" aria-controls="sidenav-5"><span>App solutions</span> <span class="material-symbols expander" aria-hidden="true">expand_more</span></button><ul class="nav collapse" id="sidenav-5"><li class="nav-item"><button class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#sidenav-5-1" role="button" aria-expanded="false" aria-controls="sidenav-5-1"><span>AI</span> <span class="material-symbols expander" aria-hidden="true">expand_more</span></button><ul class="nav collapse" id="sidenav-5-1"><li class="nav-item"><button class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#sidenav-5-1-1" role="button" aria-expanded="false" aria-controls="sidenav-5-1-1"><span>AI Toolkit guide</span> <span class="material-symbols expander" aria-hidden="true">expand_more</span></button><ul class="nav collapse" id="sidenav-5-1-1"><li class="nav-item"><a class="nav-link" href="/ai-toolkit"><div><span>Overview</span></div></a></li><li class="nav-item"><a class="nav-link" href="/ai-toolkit/user-experience"><div><span>User experience</span></div></a></li><li class="nav-item"><a class="nav-link" href="/ai-toolkit/feature-integration"><div><span>Feature integration</span></div></a></li><li class="nav-item"><a class="nav-link" href="/ai-toolkit/custom-llm-providers"><div><span>Custom LLM providers</span></div></a></li><li class="nav-item"><a class="nav-link" href="/ai-toolkit/chat-client-sample"><div><span>Chat client sample</span></div></a></li></ul></li><li class="nav-item"><a class="nav-link" href="https://www.youtube.com/watch?v=1AuzJEiHjO4" target="_blank" rel="noopener"><div><span>Build with Google AI Dart SDK (video)</span><span class="material-symbols" aria-hidden="true">open_in_new</span></div></a></li></ul></li><li class="nav-item"><button class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#sidenav-5-2" role="button" aria-expanded="false" aria-controls="sidenav-5-2"><span>Firebase & Firestore</span> <span class="material-symbols expander" aria-hidden="true">expand_more</span></button><ul class="nav collapse" id="sidenav-5-2"><li class="nav-item"><a class="nav-link" href="/data-and-backend/firebase"><div><span>Overview</span></div></a></li><li class="nav-item"><a class="nav-link" href="https://firebase.google.com/docs/flutter" target="_blank" rel="noopener"><div><span>Discover Firebase for Flutter</span><span class="material-symbols" aria-hidden="true">open_in_new</span></div></a></li><li class="nav-item"><a class="nav-link" href="https://www.youtube.com/watch?v=wUSkeTaBonA" target="_blank" rel="noopener"><div><span>Get to know Firebase for Flutter</span><span class="material-symbols" aria-hidden="true">open_in_new</span></div></a></li><li class="nav-item"><a class="nav-link" href="https://firebase.google.com/codelabs/firebase-auth-in-flutter-apps" target="_blank" rel="noopener"><div><span>Add a user authentication flow to a Flutter app using FirebaseUI</span><span class="material-symbols" aria-hidden="true">open_in_new</span></div></a></li><li class="nav-item"><a class="nav-link" href="https://firebase.google.com/codelabs/firebase-get-to-know-web" target="_blank" rel="noopener"><div><span>Get to know Firebase for web</span><span class="material-symbols" aria-hidden="true">open_in_new</span></div></a></li></ul></li><li class="nav-item"><button class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#sidenav-5-3" role="button" aria-expanded="false" aria-controls="sidenav-5-3"><span>Games</span> <span class="material-symbols expander" aria-hidden="true">expand_more</span></button><ul class="nav collapse" id="sidenav-5-3"><li class="nav-item"><a class="nav-link" href="/resources/games-toolkit"><div><span>Overview</span></div></a></li><li class="nav-item"><a class="nav-link" href="/cookbook/games/achievements-leaderboard"><div><span>Add achievements and leaderboards</span></div></a></li><li class="nav-item"><a class="nav-link" href="https://firebase.google.com/codelabs/build-leaderboards-with-firestore#0" target="_blank" rel="noopener"><div><span>Build leaderboards with Firestore</span><span class="material-symbols" aria-hidden="true">open_in_new</span></div></a></li><li class="nav-item"><a class="nav-link" href="/cookbook/plugins/google-mobile-ads"><div><span>Add advertising</span></div></a></li><li class="nav-item"><a class="nav-link" href="/cookbook/games/firestore-multiplayer"><div><span>Add multiplayer support</span></div></a></li><li class="nav-item"><a class="nav-link" href="https://codelabs.developers.google.com/codelabs/flutter-in-app-purchases" target="_blank" rel="noopener"><div><span>Add in-app purchases</span><span class="material-symbols" aria-hidden="true">open_in_new</span></div></a></li><li class="nav-item"><a class="nav-link" href="https://firebase.google.com/codelabs/firebase-auth-in-flutter-apps" target="_blank" rel="noopener"><div><span>Add user authentication</span><span class="material-symbols" aria-hidden="true">open_in_new</span></div></a></li><li class="nav-item"><a class="nav-link" href="https://firebase.google.com/docs/crashlytics/get-started?platform=flutter" target="_blank" rel="noopener"><div><span>Debug using Crashlytics</span><span class="material-symbols" aria-hidden="true">open_in_new</span></div></a></li><li class="nav-item"><a class="nav-link" href="https://codelabs.developers.google.com/codelabs/flutter-flame-brick-breaker" target="_blank" rel="noopener"><div><span>Intro to Flame with Flutter</span><span class="material-symbols" aria-hidden="true">open_in_new</span></div></a></li></ul></li><li class="nav-item"><button class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#sidenav-5-4" role="button" aria-expanded="false" aria-controls="sidenav-5-4"><span>Monetization</span> <span class="material-symbols expander" aria-hidden="true">expand_more</span></button><ul class="nav collapse" id="sidenav-5-4"><li class="nav-item"><button class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#sidenav-5-4-1" role="button" aria-expanded="false" aria-controls="sidenav-5-4-1"><span>Advertising</span> <span class="material-symbols expander" aria-hidden="true">expand_more</span></button><ul class="nav collapse" id="sidenav-5-4-1"><li class="nav-item"><a class="nav-link" href="/resources/ads-overview"><div><span>Ads overview</span></div></a></li><li class="nav-item"><a class="nav-link" href="/cookbook/plugins/google-mobile-ads"><div><span>Add advertising</span></div></a></li><li class="nav-item"><a class="nav-link" href="https://codelabs.developers.google.com/codelabs/admob-ads-in-flutter" target="_blank" rel="noopener"><div><span>Add AdMob ads to your Flutter app</span><span class="material-symbols" aria-hidden="true">open_in_new</span></div></a></li><li class="nav-item"><a class="nav-link" href="https://codelabs.developers.google.com/codelabs/admob-inline-ads-in-flutter" target="_blank" rel="noopener"><div><span>Add an AdMob banner and native inline ads</span><span class="material-symbols" aria-hidden="true">open_in_new</span></div></a></li><li class="nav-item"><a class="nav-link" href="https://developers.google.com/admob/flutter/mediation" target="_blank" rel="noopener"><div><span>Google AdMob mediation</span><span class="material-symbols" aria-hidden="true">open_in_new</span></div></a></li><li class="nav-item"><a class="nav-link" href="https://pub.dev/packages/interactive_media_ads" target="_blank" rel="noopener"><div><span>Interactive Media Ads SDK</span><span class="material-symbols" aria-hidden="true">open_in_new</span></div></a></li></ul></li><li class="nav-item"><button class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#sidenav-5-4-2" role="button" aria-expanded="false" aria-controls="sidenav-5-4-2"><span>In-app purchases</span> <span class="material-symbols expander" aria-hidden="true">expand_more</span></button><ul class="nav collapse" id="sidenav-5-4-2"><li class="nav-item"><a class="nav-link" href="/resources/in-app-purchases-overview"><div><span>In-app purchases overview</span></div></a></li><li class="nav-item"><a class="nav-link" href="https://codelabs.developers.google.com/codelabs/flutter-in-app-purchases" target="_blank" rel="noopener"><div><span>Add in-app purchases</span><span class="material-symbols" aria-hidden="true">open_in_new</span></div></a></li></ul></li><li class="nav-item"><button class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#sidenav-5-4-3" role="button" aria-expanded="false" aria-controls="sidenav-5-4-3"><span>Payments</span> <span class="material-symbols expander" aria-hidden="true">expand_more</span></button><ul class="nav collapse" id="sidenav-5-4-3"><li class="nav-item"><a class="nav-link" href="/resources/payments-overview"><div><span>Payments overview</span></div></a></li><li class="nav-item"><a class="nav-link" href="https://pub.dev/packages/pay" target="_blank" rel="noopener"><div><span>Google pay package</span><span class="material-symbols" aria-hidden="true">open_in_new</span></div></a></li></ul></li></ul></li><li class="nav-item"><button class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#sidenav-5-5" role="button" aria-expanded="false" aria-controls="sidenav-5-5"><span>Maps</span> <span class="material-symbols expander" aria-hidden="true">expand_more</span></button><ul class="nav collapse" id="sidenav-5-5"><li class="nav-item"><a class="nav-link" href="https://codelabs.developers.google.com/codelabs/google-maps-in-flutter" target="_blank" rel="noopener"><div><span>Add Google maps to a Flutter app</span><span class="material-symbols" aria-hidden="true">open_in_new</span></div></a></li><li class="nav-item"><a class="nav-link" href="https://developers.google.com/maps/flutter-package" target="_blank" rel="noopener"><div><span>Google Maps package</span><span class="material-symbols" aria-hidden="true">open_in_new</span></div></a></li></ul></li><li class="nav-item"><button class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#sidenav-5-6" role="button" aria-expanded="false" aria-controls="sidenav-5-6"><span>News</span> <span class="material-symbols expander" aria-hidden="true">expand_more</span></button><ul class="nav collapse" id="sidenav-5-6"><li class="nav-item"><a class="nav-link" href="/resources/news-toolkit"><div><span>Build a news app</span></div></a></li></ul></li></ul></li><li aria-hidden="true"><div class="sidenav-divider"></div></li><li class="nav-header">User interface</li><li class="nav-item"><a class="nav-link" href="/ui"><div><span>Introduction</span></div></a></li><li class="nav-item"><a class="nav-link" href="/ui/widgets"><div><span>Widget catalog</span></div></a></li><li class="nav-item"><button class="nav-link collapsed collapsible" data-toggle="collapse" data-target="#sidenav-10" role="button" aria-expanded="false" aria-controls="sidenav-10"><span>Layout</span> <span class="material-symbols expander" aria-hidden="true">expand_more</span></button><ul class="nav collapse" id="sidenav-10"><li class="nav-item"><a class="nav-link" href="/ui/layout"><div><span>Introduction</span></div></a></li><li class="nav-item"><a class="nav-link" href="/ui/layout/tutorial"><div><span>Build a layout</span></div></a></li><li class="nav-item"><button class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#sidenav-10-3" role="button" aria-expanded="false" aria-controls="sidenav-10-3"><span>Lists & grids</span> <span class="material-symbols expander" aria-hidden="true">expand_more</span></button><ul class="nav collapse" id="sidenav-10-3"><li class="nav-item"><a class="nav-link" href="/cookbook/lists/basic-list"><div><span>Create and use lists</span></div></a></li><li class="nav-item"><a class="nav-link" href="/cookbook/lists/horizontal-list"><div><span>Create a horizontal list</span></div></a></li><li class="nav-item"><a class="nav-link" href="/cookbook/lists/grid-lists"><div><span>Create a grid view</span></div></a></li><li class="nav-item"><a class="nav-link" href="/cookbook/lists/mixed-list"><div><span>Create lists with different types of items</span></div></a></li><li class="nav-item"><a class="nav-link" href="/cookbook/lists/spaced-items"><div><span>Create lists with spaced items</span></div></a></li><li class="nav-item"><a class="nav-link" href="/cookbook/lists/long-lists"><div><span>Work with long lists</span></div></a></li></ul></li><li class="nav-item"><button class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#sidenav-10-4" role="button" aria-expanded="false" aria-controls="sidenav-10-4"><span>Scrolling</span> <span class="material-symbols expander" aria-hidden="true">expand_more</span></button><ul class="nav collapse" id="sidenav-10-4"><li class="nav-item"><a class="nav-link" href="/ui/layout/scrolling"><div><span>Overview</span></div></a></li><li class="nav-item"><a class="nav-link" href="/ui/layout/scrolling/slivers"><div><span>Use slivers to achieve fancy scrolling</span></div></a></li><li class="nav-item"><a class="nav-link" href="/cookbook/lists/floating-app-bar"><div><span>Place a floating app bar above a list</span></div></a></li><li class="nav-item"><a class="nav-link" href="/cookbook/effects/parallax-scrolling"><div><span>Create a scrolling parallax effect</span></div></a></li></ul></li></ul></li><li class="nav-item"><button class="nav-link collapsed collapsible" data-toggle="collapse" data-target="#sidenav-11" role="button" aria-expanded="false" aria-controls="sidenav-11"><span>Adaptive & responsive design</span> <span class="material-symbols expander" aria-hidden="true">expand_more</span></button><ul class="nav collapse" id="sidenav-11"><li class="nav-item"><a class="nav-link" href="/ui/adaptive-responsive"><div><span>Overview</span></div></a></li><li class="nav-item"><a class="nav-link" href="/ui/adaptive-responsive/general"><div><span>General approach</span></div></a></li><li class="nav-item"><a class="nav-link" href="/ui/adaptive-responsive/safearea-mediaquery"><div><span>SafeArea & MediaQuery</span></div></a></li><li class="nav-item"><a class="nav-link" href="/ui/adaptive-responsive/large-screens"><div><span>Large screens & foldables</span></div></a></li><li class="nav-item"><a class="nav-link" href="/ui/adaptive-responsive/input"><div><span>User input & accessibility</span></div></a></li><li class="nav-item"><a class="nav-link" href="/ui/adaptive-responsive/capabilities"><div><span>Capabilities & policies</span></div></a></li><li class="nav-item"><a class="nav-link" href="/ui/adaptive-responsive/platform-adaptations"><div><span>Automatic platform adaptations</span></div></a></li><li class="nav-item"><a class="nav-link" href="/ui/adaptive-responsive/best-practices"><div><span>Best practices</span></div></a></li><li class="nav-item"><a class="nav-link" href="/ui/adaptive-responsive/more-info"><div><span>Additional resources</span></div></a></li></ul></li><li class="nav-item"><button class="nav-link collapsed collapsible" data-toggle="collapse" data-target="#sidenav-12" role="button" aria-expanded="false" aria-controls="sidenav-12"><span>Design & theming</span> <span class="material-symbols expander" aria-hidden="true">expand_more</span></button><ul class="nav collapse" id="sidenav-12"><li class="nav-item"><a class="nav-link" href="/cookbook/design/themes"><div><span>Share styles with themes</span></div></a></li><li class="nav-item"><a class="nav-link" href="/ui/design/material"><div><span>Material design</span></div></a></li><li class="nav-item"><a class="nav-link" href="/release/breaking-changes/material-3-migration"><div><span>Migrate to Material 3</span></div></a></li><li class="nav-item"><button class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#sidenav-12-4" role="button" aria-expanded="false" aria-controls="sidenav-12-4"><span>Text</span> <span class="material-symbols expander" aria-hidden="true">expand_more</span></button><ul class="nav collapse" id="sidenav-12-4"><li class="nav-item"><a class="nav-link" href="/ui/design/text/typography"><div><span>Fonts & typography</span></div></a></li><li class="nav-item"><a class="nav-link" href="/cookbook/design/fonts"><div><span>Use a custom font</span></div></a></li><li class="nav-item"><a class="nav-link" href="/cookbook/design/package-fonts"><div><span>Export fonts from a package</span></div></a></li><li class="nav-item"><a class="nav-link" href="https://pub.dev/packages/google_fonts" target="_blank" rel="noopener"><div><span>Google Fonts package</span><span class="material-symbols" aria-hidden="true">open_in_new</span></div></a></li></ul></li><li class="nav-item"><button class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#sidenav-12-5" role="button" aria-expanded="false" aria-controls="sidenav-12-5"><span>Custom graphics</span> <span class="material-symbols expander" aria-hidden="true">expand_more</span></button><ul class="nav collapse" id="sidenav-12-5"><li class="nav-item"><a class="nav-link" href="/ui/design/graphics/fragment-shaders"><div><span>Use custom fragment shaders</span></div></a></li></ul></li></ul></li><li class="nav-item"><button class="nav-link collapsed collapsible" data-toggle="collapse" data-target="#sidenav-13" role="button" aria-expanded="false" aria-controls="sidenav-13"><span>Interactivity</span> <span class="material-symbols expander" aria-hidden="true">expand_more</span></button><ul class="nav collapse" id="sidenav-13"><li class="nav-item"><a class="nav-link" href="/ui/interactivity"><div><span>Add interactivity to your app</span></div></a></li><li class="nav-item"><button class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#sidenav-13-2" role="button" aria-expanded="false" aria-controls="sidenav-13-2"><span>Gestures</span> <span class="material-symbols expander" aria-hidden="true">expand_more</span></button><ul class="nav collapse" id="sidenav-13-2"><li class="nav-item"><a class="nav-link" href="/ui/interactivity/gestures"><div><span>Introduction</span></div></a></li><li class="nav-item"><a class="nav-link" href="/cookbook/gestures/handling-taps"><div><span>Handle taps</span></div></a></li><li class="nav-item"><a class="nav-link" href="/ui/interactivity/gestures/drag-outside"><div><span>Drag an object outside an app</span></div></a></li><li class="nav-item"><a class="nav-link" href="/cookbook/effects/drag-a-widget"><div><span>Drag a UI element within an app</span></div></a></li><li class="nav-item"><a class="nav-link" href="/cookbook/gestures/ripples"><div><span>Add Material touch ripples</span></div></a></li><li class="nav-item"><a class="nav-link" href="/cookbook/gestures/dismissible"><div><span>Implement swipe to dismiss</span></div></a></li></ul></li><li class="nav-item"><button class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#sidenav-13-3" role="button" aria-expanded="false" aria-controls="sidenav-13-3"><span>Input & forms</span> <span class="material-symbols expander" aria-hidden="true">expand_more</span></button><ul class="nav collapse" id="sidenav-13-3"><li class="nav-item"><a class="nav-link" href="/cookbook/forms/text-input"><div><span>Create and style a text field</span></div></a></li><li class="nav-item"><a class="nav-link" href="/cookbook/forms/retrieve-input"><div><span>Retrieve the value of a text field</span></div></a></li><li class="nav-item"><a class="nav-link" href="/cookbook/forms/text-field-changes"><div><span>Handle changes to a text field</span></div></a></li><li class="nav-item"><a class="nav-link" href="/cookbook/forms/focus"><div><span>Manage focus in text fields</span></div></a></li><li class="nav-item"><a class="nav-link" href="/cookbook/forms/validation"><div><span>Build a form with validation</span></div></a></li></ul></li><li class="nav-item"><a class="nav-link" href="/cookbook/design/snackbars"><div><span>Display a snackbar</span></div></a></li><li class="nav-item"><a class="nav-link" href="/ui/interactivity/actions-and-shortcuts"><div><span>Implement actions & shortcuts</span></div></a></li><li class="nav-item"><a class="nav-link" href="/ui/interactivity/focus"><div><span>Manage keyboard focus</span></div></a></li></ul></li><li class="nav-item"><button class="nav-link collapsed collapsible" data-toggle="collapse" data-target="#sidenav-14" role="button" aria-expanded="false" aria-controls="sidenav-14"><span>Assets & media</span> <span class="material-symbols expander" aria-hidden="true">expand_more</span></button><ul class="nav collapse" id="sidenav-14"><li class="nav-item"><a class="nav-link" href="/ui/assets/assets-and-images"><div><span>Add assets and images</span></div></a></li><li class="nav-item"><a class="nav-link" href="/cookbook/images/network-image"><div><span>Display images from the internet</span></div></a></li><li class="nav-item"><a class="nav-link" href="/cookbook/images/fading-in-images"><div><span>Fade in images with a placeholder</span></div></a></li><li class="nav-item"><a class="nav-link" href="/cookbook/plugins/play-video"><div><span>Play and pause a video</span></div></a></li><li class="nav-item"><a class="nav-link" href="/ui/assets/asset-transformation"><div><span>Transform assets at build time</span></div></a></li></ul></li><li class="nav-item"><button class="nav-link collapsed collapsible" data-toggle="collapse" data-target="#sidenav-15" role="button" aria-expanded="false" aria-controls="sidenav-15"><span>Navigation & routing</span> <span class="material-symbols expander" aria-hidden="true">expand_more</span></button><ul class="nav collapse" id="sidenav-15"><li class="nav-item"><a class="nav-link" href="/ui/navigation"><div><span>Overview</span></div></a></li><li class="nav-item"><a class="nav-link" href="/cookbook/design/tabs"><div><span>Add tabs to your app</span></div></a></li><li class="nav-item"><a class="nav-link" href="/cookbook/navigation/navigation-basics"><div><span>Navigate to a new screen and back</span></div></a></li><li class="nav-item"><a class="nav-link" href="/cookbook/navigation/passing-data"><div><span>Send data to a new screen</span></div></a></li><li class="nav-item"><a class="nav-link" href="/cookbook/navigation/returning-data"><div><span>Return data from a screen</span></div></a></li><li class="nav-item"><a class="nav-link" href="/cookbook/design/drawer"><div><span>Add a drawer to a screen</span></div></a></li><li class="nav-item"><a class="nav-link" href="/ui/navigation/deep-linking"><div><span>Set up deep linking</span></div></a></li><li class="nav-item"><a class="nav-link" href="/cookbook/navigation/set-up-app-links"><div><span>Set up app links for Android</span></div></a></li><li class="nav-item"><a class="nav-link" href="/cookbook/navigation/set-up-universal-links"><div><span>Set up universal links for iOS</span></div></a></li><li class="nav-item"><a class="nav-link" href="/ui/navigation/url-strategies"><div><span>Configure web URL strategies</span></div></a></li></ul></li><li class="nav-item"><button class="nav-link collapsed collapsible" data-toggle="collapse" data-target="#sidenav-16" role="button" aria-expanded="false" aria-controls="sidenav-16"><span>Animations & transitions</span> <span class="material-symbols expander" aria-hidden="true">expand_more</span></button><ul class="nav collapse" id="sidenav-16"><li class="nav-item"><a class="nav-link" href="/ui/animations"><div><span>Introduction</span></div></a></li><li class="nav-item"><a class="nav-link" href="/ui/animations/tutorial"><div><span>Tutorial</span></div></a></li><li class="nav-item"><a class="nav-link" href="/ui/animations/implicit-animations"><div><span>Implicit animations</span></div></a></li><li class="nav-item"><a class="nav-link" href="/cookbook/animation/animated-container"><div><span>Animate the properties of a container</span></div></a></li><li class="nav-item"><a class="nav-link" href="/cookbook/animation/opacity-animation"><div><span>Fade a widget in and out</span></div></a></li><li class="nav-item"><a class="nav-link" href="/ui/animations/hero-animations"><div><span>Hero animations</span></div></a></li><li class="nav-item"><a class="nav-link" href="/cookbook/animation/page-route-animation"><div><span>Animate a page route transition</span></div></a></li><li class="nav-item"><a class="nav-link" href="/cookbook/animation/physics-simulation"><div><span>Animate using a physics simulation</span></div></a></li><li class="nav-item"><a class="nav-link" href="/ui/animations/staggered-animations"><div><span>Staggered animations</span></div></a></li><li class="nav-item"><a class="nav-link" href="/cookbook/effects/staggered-menu-animation"><div><span>Create a staggered menu animation</span></div></a></li><li class="nav-item"><a class="nav-link" href="/ui/animations/overview"><div><span>API overview</span></div></a></li></ul></li><li class="nav-item"><button class="nav-link collapsed collapsible" data-toggle="collapse" data-target="#sidenav-17" role="button" aria-expanded="false" aria-controls="sidenav-17"><span>Accessibility & internationalization</span> <span class="material-symbols expander" aria-hidden="true">expand_more</span></button><ul class="nav collapse" id="sidenav-17"><li class="nav-item"><a class="nav-link" href="/ui/accessibility-and-internationalization/accessibility"><div><span>Accessibility</span></div></a></li><li class="nav-item"><a class="nav-link" href="/ui/accessibility-and-internationalization/internationalization"><div><span>Internationalization</span></div></a></li></ul></li><li aria-hidden="true"><div class="sidenav-divider"></div></li><li class="nav-header">Beyond UI</li><li class="nav-item"><button class="nav-link collapsed collapsible" data-toggle="collapse" data-target="#sidenav-20" role="button" aria-expanded="false" aria-controls="sidenav-20"><span>Data & backend</span> <span class="material-symbols expander" aria-hidden="true">expand_more</span></button><ul class="nav collapse" id="sidenav-20"><li class="nav-item"><button class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#sidenav-20-1" role="button" aria-expanded="false" aria-controls="sidenav-20-1"><span>State management</span> <span class="material-symbols expander" aria-hidden="true">expand_more</span></button><ul class="nav collapse" id="sidenav-20-1"><li class="nav-item"><a class="nav-link" href="/data-and-backend/state-mgmt/intro"><div><span>Introduction</span></div></a></li><li class="nav-item"><a class="nav-link" href="/data-and-backend/state-mgmt/declarative"><div><span>Think declaratively</span></div></a></li><li class="nav-item"><a class="nav-link" href="/data-and-backend/state-mgmt/ephemeral-vs-app"><div><span>Ephemeral vs app state</span></div></a></li><li class="nav-item"><a class="nav-link" href="/data-and-backend/state-mgmt/simple"><div><span>Simple app state management</span></div></a></li><li class="nav-item"><a class="nav-link" href="/data-and-backend/state-mgmt/options"><div><span>Options</span></div></a></li></ul></li><li class="nav-item"><button class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#sidenav-20-2" role="button" aria-expanded="false" aria-controls="sidenav-20-2"><span>Networking & http</span> <span class="material-symbols expander" aria-hidden="true">expand_more</span></button><ul class="nav collapse" id="sidenav-20-2"><li class="nav-item"><a class="nav-link" href="/data-and-backend/networking"><div><span>Overview</span></div></a></li><li class="nav-item"><a class="nav-link" href="/cookbook/networking/fetch-data"><div><span>Fetch data from the internet</span></div></a></li><li class="nav-item"><a class="nav-link" href="/cookbook/networking/authenticated-requests"><div><span>Make authenticated requests</span></div></a></li><li class="nav-item"><a class="nav-link" href="/cookbook/networking/send-data"><div><span>Send data to the internet</span></div></a></li><li class="nav-item"><a class="nav-link" href="/cookbook/networking/update-data"><div><span>Update data over the internet</span></div></a></li><li class="nav-item"><a class="nav-link" href="/cookbook/networking/delete-data"><div><span>Delete data on the internet</span></div></a></li><li class="nav-item"><a class="nav-link" href="/cookbook/networking/web-sockets"><div><span>Communicate with WebSockets</span></div></a></li></ul></li><li class="nav-item"><button class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#sidenav-20-3" role="button" aria-expanded="false" aria-controls="sidenav-20-3"><span>Serialization</span> <span class="material-symbols expander" aria-hidden="true">expand_more</span></button><ul class="nav collapse" id="sidenav-20-3"><li class="nav-item"><a class="nav-link" href="/data-and-backend/serialization/json"><div><span>JSON serialization</span></div></a></li><li class="nav-item"><a class="nav-link" href="/cookbook/networking/background-parsing"><div><span>Parse JSON in the background</span></div></a></li></ul></li><li class="nav-item"><button class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#sidenav-20-4" role="button" aria-expanded="false" aria-controls="sidenav-20-4"><span>Persistence</span> <span class="material-symbols expander" aria-hidden="true">expand_more</span></button><ul class="nav collapse" id="sidenav-20-4"><li class="nav-item"><a class="nav-link" href="/cookbook/persistence/key-value"><div><span>Store key-value data on disk</span></div></a></li><li class="nav-item"><a class="nav-link" href="/cookbook/persistence/reading-writing-files"><div><span>Read and write files</span></div></a></li><li class="nav-item"><a class="nav-link" href="/cookbook/persistence/sqlite"><div><span>Persist data with SQLite</span></div></a></li></ul></li><li class="nav-item"><button class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#sidenav-20-5" role="button" aria-expanded="false" aria-controls="sidenav-20-5"><span>Firebase</span> <span class="material-symbols expander" aria-hidden="true">expand_more</span></button><ul class="nav collapse" id="sidenav-20-5"><li class="nav-item"><a class="nav-link" href="/data-and-backend/firebase"><div><span>Overview</span></div></a></li><li class="nav-item"><a class="nav-link" href="https://firebase.google.com/docs/flutter/setup" target="_blank" rel="noopener"><div><span>Add Firebase to your Flutter app</span><span class="material-symbols" aria-hidden="true">open_in_new</span></div></a></li></ul></li><li class="nav-item"><a class="nav-link" href="/data-and-backend/google-apis"><div><span>Google APIs</span></div></a></li></ul></li><li class="nav-item"><button class="nav-link collapsed collapsible" data-toggle="collapse" data-target="#sidenav-21" role="button" aria-expanded="false" aria-controls="sidenav-21"><span>App architecture</span> <span class="material-symbols expander" aria-hidden="true">expand_more</span></button><ul class="nav collapse" id="sidenav-21"><li class="nav-item"><a class="nav-link" href="/app-architecture"><div><span>Introduction</span></div></a></li><li class="nav-item"><a class="nav-link" href="/app-architecture/concepts"><div><span>Architecture concepts</span></div></a></li><li class="nav-item"><a class="nav-link" href="/app-architecture/guide"><div><span>Guide to app architecture</span></div></a></li><li class="nav-item"><button class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#sidenav-21-4" role="button" aria-expanded="false" aria-controls="sidenav-21-4"><span>Architecture case study</span> <span class="material-symbols expander" aria-hidden="true">expand_more</span></button><ul class="nav collapse" id="sidenav-21-4"><li class="nav-item"><a class="nav-link" href="/app-architecture/case-study"><div><span>Overview</span></div></a></li><li class="nav-item"><a class="nav-link" href="/app-architecture/case-study/ui-layer"><div><span>UI layer</span></div></a></li><li class="nav-item"><a class="nav-link" href="/app-architecture/case-study/data-layer"><div><span>Data layer</span></div></a></li><li class="nav-item"><a class="nav-link" href="/app-architecture/case-study/dependency-injection"><div><span>Dependency injection</span></div></a></li><li class="nav-item"><a class="nav-link" href="/app-architecture/case-study/testing"><div><span>Testing each layer</span></div></a></li></ul></li><li class="nav-item"><a class="nav-link" href="/app-architecture/recommendations"><div><span>Recommendations</span></div></a></li><li class="nav-item"><a class="nav-link" href="/app-architecture/design-patterns"><div><span>Design patterns</span></div></a></li></ul></li><li class="nav-item"><button class="nav-link collapsed collapsible" data-toggle="collapse" data-target="#sidenav-22" role="button" aria-expanded="false" aria-controls="sidenav-22"><span>Platform integration</span> <span class="material-symbols expander" aria-hidden="true">expand_more</span></button><ul class="nav collapse" id="sidenav-22"><li class="nav-item"><a class="nav-link" href="/reference/supported-platforms"><div><span>Supported platforms</span></div></a></li><li class="nav-item"><a class="nav-link" href="/platform-integration/desktop"><div><span>Build desktop apps with Flutter</span></div></a></li><li class="nav-item"><a class="nav-link" href="/platform-integration/platform-channels"><div><span>Write platform-specific code</span></div></a></li><li class="nav-item"><button class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#sidenav-22-4" role="button" aria-expanded="false" aria-controls="sidenav-22-4"><span>Android</span> <span class="material-symbols expander" aria-hidden="true">expand_more</span></button><ul class="nav collapse" id="sidenav-22-4"><li class="nav-item"><a class="nav-link" href="/platform-integration/android/install-android"><div><span>Add Android as build target</span></div></a></li><li class="nav-item"><a class="nav-link" href="/platform-integration/android/splash-screen"><div><span>Add a splash screen</span></div></a></li><li class="nav-item"><a class="nav-link" href="/platform-integration/android/predictive-back"><div><span>Add predictive back</span></div></a></li><li class="nav-item"><a class="nav-link" href="/platform-integration/android/c-interop"><div><span>Bind to native code</span></div></a></li><li class="nav-item"><a class="nav-link" href="/platform-integration/android/platform-views"><div><span>Host a native Android view</span></div></a></li><li class="nav-item"><a class="nav-link" href="/platform-integration/android/call-jetpack-apis"><div><span>Calling JetPack APIs</span></div></a></li><li class="nav-item"><a class="nav-link" href="/platform-integration/android/compose-activity"><div><span>Launch a Jetpack Compose activity</span></div></a></li><li class="nav-item"><a class="nav-link" href="/platform-integration/android/restore-state-android"><div><span>Restore state on Android</span></div></a></li><li class="nav-item"><a class="nav-link" href="/platform-integration/android/chromeos"><div><span>Target ChromeOS with Android</span></div></a></li></ul></li><li class="nav-item"><button class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#sidenav-22-5" role="button" aria-expanded="false" aria-controls="sidenav-22-5"><span>iOS</span> <span class="material-symbols expander" aria-hidden="true">expand_more</span></button><ul class="nav collapse" id="sidenav-22-5"><li class="nav-item"><a class="nav-link" href="/platform-integration/ios/install-ios"><div><span>Add iOS as build target</span></div></a></li><li class="nav-item"><a class="nav-link" href="/platform-integration/ios/ios-latest"><div><span>Flutter on latest iOS</span></div></a></li><li class="nav-item"><a class="nav-link" href="/platform-integration/ios/apple-frameworks"><div><span>Leverage Apple's system libraries</span></div></a></li><li class="nav-item"><a class="nav-link" href="/platform-integration/ios/launch-screen"><div><span>Add a launch screen</span></div></a></li><li class="nav-item"><a class="nav-link" href="/platform-integration/ios/ios-app-clip"><div><span>Add iOS App Clip support</span></div></a></li><li class="nav-item"><a class="nav-link" href="/platform-integration/ios/app-extensions"><div><span>Add iOS app extensions</span></div></a></li><li class="nav-item"><a class="nav-link" href="/platform-integration/ios/c-interop"><div><span>Bind to native code</span></div></a></li><li class="nav-item"><a class="nav-link" href="/platform-integration/ios/platform-views"><div><span>Host a native iOS view</span></div></a></li><li class="nav-item"><a class="nav-link" href="/platform-integration/ios/ios-debugging"><div><span>Enable debugging on iOS</span></div></a></li><li class="nav-item"><a class="nav-link" href="/platform-integration/ios/restore-state-ios"><div><span>Restore state on iOS</span></div></a></li></ul></li><li class="nav-item"><button class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#sidenav-22-6" role="button" aria-expanded="false" aria-controls="sidenav-22-6"><span>Linux</span> <span class="material-symbols expander" aria-hidden="true">expand_more</span></button><ul class="nav collapse" id="sidenav-22-6"><li class="nav-item"><a class="nav-link" href="/platform-integration/linux/install-linux"><div><span>Add Linux as build target</span></div></a></li><li class="nav-item"><a class="nav-link" href="/platform-integration/linux/building"><div><span>Build a Linux app</span></div></a></li></ul></li><li class="nav-item"><button class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#sidenav-22-7" role="button" aria-expanded="false" aria-controls="sidenav-22-7"><span>macOS</span> <span class="material-symbols expander" aria-hidden="true">expand_more</span></button><ul class="nav collapse" id="sidenav-22-7"><li class="nav-item"><a class="nav-link" href="/platform-integration/macos/install-macos"><div><span>Add macOS as build target</span></div></a></li><li class="nav-item"><a class="nav-link" href="/platform-integration/macos/building"><div><span>Build a macOS app</span></div></a></li><li class="nav-item"><a class="nav-link" href="/platform-integration/macos/c-interop"><div><span>Bind to native code</span></div></a></li><li class="nav-item"><a class="nav-link" href="/platform-integration/macos/platform-views"><div><span>Host a native macOS view</span></div></a></li></ul></li><li class="nav-item"><button class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#sidenav-22-8" role="button" aria-expanded="false" aria-controls="sidenav-22-8"><span>Web</span> <span class="material-symbols expander" aria-hidden="true">expand_more</span></button><ul class="nav collapse" id="sidenav-22-8"><li class="nav-item"><a class="nav-link" href="/platform-integration/web"><div><span>Web support in Flutter</span></div></a></li><li class="nav-item"><a class="nav-link" href="/platform-integration/web/install-web"><div><span>Add web as build target</span></div></a></li><li class="nav-item"><a class="nav-link" href="/platform-integration/web/building"><div><span>Build a web app</span></div></a></li><li class="nav-item"><a class="nav-link" href="/platform-integration/web/wasm"><div><span>Compile to WebAssembly</span></div></a></li><li class="nav-item"><a class="nav-link" href="/platform-integration/web/initialization"><div><span>Customize app initialization</span></div></a></li><li class="nav-item"><a class="nav-link" href="/platform-integration/web/embedding-flutter-web"><div><span>Add Flutter to any web app</span></div></a></li><li class="nav-item"><a class="nav-link" href="/platform-integration/web/web-content-in-flutter"><div><span>Web content in Flutter</span></div></a></li><li class="nav-item"><a class="nav-link" href="/platform-integration/web/renderers"><div><span>Web renderers</span></div></a></li><li class="nav-item"><a class="nav-link" href="/platform-integration/web/web-images"><div><span>Display images on the web</span></div></a></li><li class="nav-item"><a class="nav-link" href="/platform-integration/web/faq"><div><span>Web FAQ</span></div></a></li></ul></li><li class="nav-item"><button class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#sidenav-22-9" role="button" aria-expanded="false" aria-controls="sidenav-22-9"><span>Windows</span> <span class="material-symbols expander" aria-hidden="true">expand_more</span></button><ul class="nav collapse" id="sidenav-22-9"><li class="nav-item"><a class="nav-link" href="/platform-integration/windows/install-windows"><div><span>Add Windows as build target</span></div></a></li><li class="nav-item"><a class="nav-link" href="/platform-integration/windows/building"><div><span>Build a Windows app</span></div></a></li></ul></li></ul></li><li class="nav-item"><button class="nav-link collapsed collapsible" data-toggle="collapse" data-target="#sidenav-23" role="button" aria-expanded="false" aria-controls="sidenav-23"><span>Packages & plugins</span> <span class="material-symbols expander" aria-hidden="true">expand_more</span></button><ul class="nav collapse" id="sidenav-23"><li class="nav-item"><a class="nav-link" href="/packages-and-plugins/using-packages"><div><span>Use packages & plugins</span></div></a></li><li class="nav-item"><a class="nav-link" href="/packages-and-plugins/developing-packages"><div><span>Develop packages & plugins</span></div></a></li><li class="nav-item"><button class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#sidenav-23-3" role="button" aria-expanded="false" aria-controls="sidenav-23-3"><span>Swift Package Manager</span> <span class="material-symbols expander" aria-hidden="true">expand_more</span></button><ul class="nav collapse" id="sidenav-23-3"><li class="nav-item"><a class="nav-link" href="/packages-and-plugins/swift-package-manager/for-app-developers"><div><span>For app developers</span></div></a></li><li class="nav-item"><a class="nav-link" href="/packages-and-plugins/swift-package-manager/for-plugin-authors"><div><span>For plugin authors</span></div></a></li></ul></li><div class="sidenav-divider"></div><li class="nav-item"><a class="nav-link" href="/packages-and-plugins/favorites"><div><span>Flutter Favorites</span></div></a></li><li class="nav-item"><a class="nav-link" href="https://pub.dev/flutter" target="_blank" rel="noopener"><div><span>Package repository</span><span class="material-symbols" aria-hidden="true">open_in_new</span></div></a></li></ul></li><li class="nav-item"><button class="nav-link collapsed collapsible" data-toggle="collapse" data-target="#sidenav-24" role="button" aria-expanded="false" aria-controls="sidenav-24"><span>Testing & debugging</span> <span class="material-symbols expander" aria-hidden="true">expand_more</span></button><ul class="nav collapse" id="sidenav-24"><li class="nav-header">Testing</li><li class="nav-item"><a class="nav-link" href="/testing/overview"><div><span>Overview</span></div></a></li><li class="nav-item"><button class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#sidenav-24-3" role="button" aria-expanded="false" aria-controls="sidenav-24-3"><span>Unit testing</span> <span class="material-symbols expander" aria-hidden="true">expand_more</span></button><ul class="nav collapse" id="sidenav-24-3"><li class="nav-item"><a class="nav-link" href="/cookbook/testing/unit/introduction"><div><span>Introduction</span></div></a></li><li class="nav-item"><a class="nav-link" href="/cookbook/testing/unit/mocking"><div><span>Mock dependencies</span></div></a></li></ul></li><li class="nav-item"><button class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#sidenav-24-4" role="button" aria-expanded="false" aria-controls="sidenav-24-4"><span>Widget testing</span> <span class="material-symbols expander" aria-hidden="true">expand_more</span></button><ul class="nav collapse" id="sidenav-24-4"><li class="nav-item"><a class="nav-link" href="/cookbook/testing/widget/introduction"><div><span>Introduction</span></div></a></li><li class="nav-item"><a class="nav-link" href="/cookbook/testing/widget/finders"><div><span>Find widgets</span></div></a></li><li class="nav-item"><a class="nav-link" href="/cookbook/testing/widget/scrolling"><div><span>Simulate scrolling</span></div></a></li><li class="nav-item"><a class="nav-link" href="/cookbook/testing/widget/tap-drag"><div><span>Simulate user interaction</span></div></a></li></ul></li><li class="nav-item"><button class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#sidenav-24-5" role="button" aria-expanded="false" aria-controls="sidenav-24-5"><span>Integration testing</span> <span class="material-symbols expander" aria-hidden="true">expand_more</span></button><ul class="nav collapse" id="sidenav-24-5"><li class="nav-item"><a class="nav-link" href="/cookbook/testing/integration/introduction"><div><span>Introduction</span></div></a></li><li class="nav-item"><a class="nav-link" href="/testing/integration-tests"><div><span>Write and run an integration test</span></div></a></li><li class="nav-item"><a class="nav-link" href="/cookbook/testing/integration/profiling"><div><span>Profile an integration test</span></div></a></li></ul></li><li class="nav-item"><a class="nav-link" href="/testing/testing-plugins"><div><span>Test a plugin</span></div></a></li><li class="nav-item"><a class="nav-link" href="/testing/plugins-in-tests"><div><span>Handle plugin code in tests</span></div></a></li><li class="nav-header">Debugging</li><li class="nav-item"><a class="nav-link" href="/testing/debugging"><div><span>Debugging tools</span></div></a></li><li class="nav-item"><a class="nav-link" href="/testing/code-debugging"><div><span>Debug your app programmatically</span></div></a></li><li class="nav-item"><a class="nav-link" href="/testing/native-debugging"><div><span>Use a native language debugger</span></div></a></li><li class="nav-item"><a class="nav-link" href="/testing/common-errors"><div><span>Common Flutter errors</span></div></a></li><li class="nav-item"><a class="nav-link" href="/testing/errors"><div><span>Handle errors</span></div></a></li><li class="nav-item"><a class="nav-link" href="/cookbook/maintenance/error-reporting"><div><span>Report errors to a service</span></div></a></li></ul></li><li class="nav-item"><button class="nav-link collapsed collapsible" data-toggle="collapse" data-target="#sidenav-25" role="button" aria-expanded="false" aria-controls="sidenav-25"><span>Performance & optimization</span> <span class="material-symbols expander" aria-hidden="true">expand_more</span></button><ul class="nav collapse" id="sidenav-25"><li class="nav-item"><a class="nav-link" href="/perf"><div><span>Overview</span></div></a></li><li class="nav-item"><a class="nav-link" href="/perf/impeller"><div><span>Impeller</span></div></a></li><li class="nav-item"><a class="nav-link" href="/perf/best-practices"><div><span>Performance best practices</span></div></a></li><li class="nav-item"><a class="nav-link" href="/perf/app-size"><div><span>App size</span></div></a></li><li class="nav-item"><a class="nav-link" href="/perf/deferred-components"><div><span>Deferred components</span></div></a></li><li class="nav-item"><a class="nav-link" href="/perf/rendering-performance"><div><span>Rendering performance</span></div></a></li><li class="nav-item"><a class="nav-link" href="/perf/ui-performance"><div><span>Performance profiling</span></div></a></li><li class="nav-item"><a class="nav-link" href="/perf/web-performance"><div><span>Performance profiling for web</span></div></a></li><li class="nav-item"><a class="nav-link" href="/perf/metrics"><div><span>Performance metrics</span></div></a></li><li class="nav-item"><a class="nav-link" href="/perf/isolates"><div><span>Concurrency and isolates</span></div></a></li><li class="nav-item"><a class="nav-link" href="/perf/faq"><div><span>Performance FAQ</span></div></a></li><li class="nav-item"><a class="nav-link" href="/perf/appendix"><div><span>Appendix</span></div></a></li></ul></li><li class="nav-item"><button class="nav-link collapsed collapsible" data-toggle="collapse" data-target="#sidenav-26" role="button" aria-expanded="false" aria-controls="sidenav-26"><span>Deployment</span> <span class="material-symbols expander" aria-hidden="true">expand_more</span></button><ul class="nav collapse" id="sidenav-26"><li class="nav-item"><a class="nav-link" href="/deployment/obfuscate"><div><span>Obfuscate Dart code</span></div></a></li><li class="nav-item"><a class="nav-link" href="/deployment/flavors"><div><span>Create app flavors for Android</span></div></a></li><li class="nav-item"><a class="nav-link" href="/deployment/flavors-ios"><div><span>Create app flavors for iOS and macOS</span></div></a></li><li class="nav-item"><a class="nav-link" href="/deployment/android"><div><span>Build and release an Android app</span></div></a></li><li class="nav-item"><a class="nav-link" href="/deployment/ios"><div><span>Build and release an iOS app</span></div></a></li><li class="nav-item"><a class="nav-link" href="/deployment/macos"><div><span>Build and release a macOS app</span></div></a></li><li class="nav-item"><a class="nav-link" href="/deployment/linux"><div><span>Build and release a Linux app</span></div></a></li><li class="nav-item"><a class="nav-link" href="/deployment/windows"><div><span>Build and release a Windows app</span></div></a></li><li class="nav-item"><a class="nav-link" href="/deployment/web"><div><span>Build and release a web app</span></div></a></li><li class="nav-item"><a class="nav-link" href="/deployment/cd"><div><span>Set up continuous deployment</span></div></a></li></ul></li><li class="nav-item"><button class="nav-link collapsed collapsible" data-toggle="collapse" data-target="#sidenav-27" role="button" aria-expanded="false" aria-controls="sidenav-27"><span>Add to an existing app</span> <span class="material-symbols expander" aria-hidden="true">expand_more</span></button><ul class="nav collapse" id="sidenav-27"><li class="nav-item"><a class="nav-link" href="/add-to-app"><div><span>Introduction</span></div></a></li><li class="nav-item"><button class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#sidenav-27-2" role="button" aria-expanded="false" aria-controls="sidenav-27-2"><span>Add to an Android app</span> <span class="material-symbols expander" aria-hidden="true">expand_more</span></button><ul class="nav collapse" id="sidenav-27-2"><li class="nav-item"><a class="nav-link" href="/add-to-app/android/project-setup"><div><span>Set up Android project</span></div></a></li><li class="nav-item"><a class="nav-link" href="/add-to-app/android/add-flutter-screen"><div><span>Add a single Flutter screen</span></div></a></li><li class="nav-item"><a class="nav-link" href="/add-to-app/android/add-flutter-fragment"><div><span>Add a Flutter Fragment</span></div></a></li><li class="nav-item"><a class="nav-link" href="/add-to-app/android/add-flutter-view"><div><span>Add a Flutter View</span></div></a></li><li class="nav-item"><a class="nav-link" href="/add-to-app/android/plugin-setup"><div><span>Use a Flutter plugin</span></div></a></li></ul></li><li class="nav-item"><button class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#sidenav-27-3" role="button" aria-expanded="false" aria-controls="sidenav-27-3"><span>Add to an iOS app</span> <span class="material-symbols expander" aria-hidden="true">expand_more</span></button><ul class="nav collapse" id="sidenav-27-3"><li class="nav-item"><a class="nav-link" href="/add-to-app/ios/project-setup"><div><span>Set up iOS project</span></div></a></li><li class="nav-item"><a class="nav-link" href="/add-to-app/ios/add-flutter-screen"><div><span>Add a single Flutter screen</span></div></a></li></ul></li><li class="nav-item"><a class="nav-link" href="/platform-integration/web/embedding-flutter-web"><div><span>Add to a web app</span></div></a></li><li class="nav-item"><a class="nav-link" href="/add-to-app/debugging"><div><span>Debug embedded Flutter module</span></div></a></li><li class="nav-item"><a class="nav-link" href="/add-to-app/multiple-flutters"><div><span>Add multiple Flutter instances</span></div></a></li><li class="nav-item"><a class="nav-link" href="/add-to-app/performance"><div><span>Loading sequence and performance</span></div></a></li></ul></li><li aria-hidden="true"><div class="sidenav-divider"></div></li><li class="nav-item"><button class="nav-link collapsed collapsible" data-toggle="collapse" data-target="#sidenav-29" role="button" aria-expanded="false" aria-controls="sidenav-29"><span>Tools & editors</span> <span class="material-symbols expander" aria-hidden="true">expand_more</span></button><ul class="nav collapse" id="sidenav-29"><li class="nav-item"><a class="nav-link" href="/tools/android-studio"><div><span>Android Studio & IntelliJ</span></div></a></li><li class="nav-item"><a class="nav-link" href="/tools/vs-code"><div><span>Visual Studio Code</span></div></a></li><li class="nav-item"><button class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#sidenav-29-3" role="button" aria-expanded="false" aria-controls="sidenav-29-3"><span>DevTools</span> <span class="material-symbols expander" aria-hidden="true">expand_more</span></button><ul class="nav collapse" id="sidenav-29-3"><li class="nav-item"><a class="nav-link" href="/tools/devtools"><div><span>Overview</span></div></a></li><li class="nav-item"><a class="nav-link" href="/tools/devtools/android-studio"><div><span>Run from Android Studio & IntelliJ</span></div></a></li><li class="nav-item"><a class="nav-link" href="/tools/devtools/vscode"><div><span>Run from VS Code</span></div></a></li><li class="nav-item"><a class="nav-link" href="/tools/devtools/cli"><div><span>Run from command line</span></div></a></li><li class="nav-item"><a class="nav-link" href="/tools/devtools/inspector"><div><span>Flutter inspector</span></div></a></li><li class="nav-item"><a class="nav-link" href="/tools/devtools/legacy-inspector"><div><span>Legacy Flutter inspector</span></div></a></li><li class="nav-item"><a class="nav-link" href="/tools/devtools/performance"><div><span>Performance view</span></div></a></li><li class="nav-item"><a class="nav-link" href="/tools/devtools/cpu-profiler"><div><span>CPU Profiler view</span></div></a></li><li class="nav-item"><a class="nav-link" href="/tools/devtools/memory"><div><span>Memory view</span></div></a></li><li class="nav-item"><a class="nav-link" href="/tools/devtools/console"><div><span>Debug console view</span></div></a></li><li class="nav-item"><a class="nav-link" href="/tools/devtools/network"><div><span>Network view</span></div></a></li><li class="nav-item"><a class="nav-link" href="/tools/devtools/debugger"><div><span>Debugger</span></div></a></li><li class="nav-item"><a class="nav-link" href="/tools/devtools/logging"><div><span>Logging view</span></div></a></li><li class="nav-item"><a class="nav-link" href="/tools/devtools/app-size"><div><span>App size tool</span></div></a></li><li class="nav-item"><a class="nav-link" href="/tools/devtools/extensions"><div><span>DevTools extensions</span></div></a></li><li class="nav-item"><a class="nav-link" href="/tools/devtools/deep-links"><div><span>Validate deep links</span></div></a></li><li class="nav-item"><a class="nav-link" href="/tools/devtools/release-notes"><div><span>Release notes</span></div></a></li></ul></li><li class="nav-item"><a class="nav-link" href="/tools/sdk"><div><span>SDK overview</span></div></a></li><li class="nav-item"><a class="nav-link" href="/tools/pubspec"><div><span>Flutter's pubspec options</span></div></a></li><li class="nav-item"><a class="nav-link" href="/tools/flutter-fix"><div><span>Automated fixes</span></div></a></li><li class="nav-item"><a class="nav-link" href="/tools/formatting"><div><span>Code formatting</span></div></a></li></ul></li><li class="nav-item"><button class="nav-link active collapsible" data-toggle="collapse" data-target="#sidenav-30" role="button" aria-expanded="true" aria-controls="sidenav-30"><span>Flutter concepts</span> <span class="material-symbols expander" aria-hidden="true">expand_more</span></button><ul class="nav collapse show" id="sidenav-30"><li class="nav-item"><a class="nav-link active" href="/resources/architectural-overview"><div><span>Architectural overview</span></div></a></li><li class="nav-item"><a class="nav-link" href="/resources/inside-flutter"><div><span>Inside Flutter</span></div></a></li><li class="nav-item"><a class="nav-link" href="/ui/layout/constraints"><div><span>Understanding constraints</span></div></a></li><li class="nav-item"><a class="nav-link" href="/testing/build-modes"><div><span>Flutter's build modes</span></div></a></li><li class="nav-item"><a class="nav-link" href="/tools/hot-reload"><div><span>Hot reload</span></div></a></li></ul></li><li class="nav-item"><button class="nav-link collapsed collapsible" data-toggle="collapse" data-target="#sidenav-31" role="button" aria-expanded="false" aria-controls="sidenav-31"><span>Resources</span> <span class="material-symbols expander" aria-hidden="true">expand_more</span></button><ul class="nav collapse" id="sidenav-31"><li class="nav-item"><a class="nav-link" href="/resources/faq"><div><span>FAQ</span></div></a></li><li class="nav-item"><a class="nav-link" href="/resources/books"><div><span>Books</span></div></a></li><li class="nav-item"><a class="nav-link" href="/resources/videos"><div><span>Videos</span></div></a></li><li class="nav-item"><a class="nav-link" href="/resources/courses"><div><span>Courses</span></div></a></li><li class="nav-item"><a class="nav-link" href="/resources/bootstrap-into-dart"><div><span>Learn Dart</span></div></a></li><li class="nav-item"><a class="nav-link" href="/resources/support"><div><span>Get support</span></div></a></li><div class="sidenav-divider"></div><li class="nav-item"><button class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#sidenav-31-8" role="button" aria-expanded="false" aria-controls="sidenav-31-8"><span>Contribute</span> <span class="material-symbols expander" aria-hidden="true">expand_more</span></button><ul class="nav collapse" id="sidenav-31-8"><li class="nav-item"><a class="nav-link" href="/resources/bug-reports"><div><span>Create useful bug reports</span></div></a></li><li class="nav-item"><a class="nav-link" href="https://github.com/flutter/flutter/blob/main/CONTRIBUTING.md" target="_blank" rel="noopener"><div><span>Contribute to Flutter</span><span class="material-symbols" aria-hidden="true">open_in_new</span></div></a></li><li class="nav-item"><a class="nav-link" href="/resources/design-docs"><div><span>Discover proposed features</span></div></a></li></ul></li><li class="nav-item"><button class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#sidenav-31-9" role="button" aria-expanded="false" aria-controls="sidenav-31-9"><span>Reference</span> <span class="material-symbols expander" aria-hidden="true">expand_more</span></button><ul class="nav collapse" id="sidenav-31-9"><li class="nav-item"><a class="nav-link" href="/dash"><div><span>Who is Dash?</span></div></a></li><li class="nav-item"><a class="nav-link" href="/reference/widgets"><div><span>Widget index</span></div></a></li><li class="nav-item"><a class="nav-link" href="/reference/flutter-cli"><div><span>flutter CLI</span></div></a></li><li class="nav-item"><a class="nav-link" href="https://api.flutter.dev" target="_blank" rel="noopener"><div><span>API docs</span><span class="material-symbols" aria-hidden="true">open_in_new</span></div></a></li></ul></li></ul></li></ul></nav></div><main class="site-content"><div id="site-toc--side" class="site-toc"><header class="site-toc__title">Contents</header><ul class="section-nav"><li class="toc-entry nav-item"><a class="nav-link" href="#architectural-layers">Architectural layers</a></li><li class="toc-entry nav-item"><a class="nav-link" href="#anatomy-of-an-app">Anatomy of an app</a></li><li class="toc-entry nav-item"><a class="nav-link" href="#reactive-user-interfaces">Reactive user interfaces</a></li><li class="toc-entry nav-item"><a class="nav-link" href="#widgets">Widgets</a><ul class="nav"><li class="toc-entry nav-item"><a class="nav-link" href="#composition">Composition</a></li><li class="toc-entry nav-item"><a class="nav-link" href="#building-widgets">Building widgets</a></li><li class="toc-entry nav-item"><a class="nav-link" href="#widget-state">Widget state</a></li><li class="toc-entry nav-item"><a class="nav-link" href="#state-management">State management</a></li></ul></li><li class="toc-entry nav-item"><a class="nav-link" href="#rendering-and-layout">Rendering and layout</a><ul class="nav"><li class="toc-entry nav-item"><a class="nav-link" href="#flutters-rendering-model">Flutter's rendering model</a></li><li class="toc-entry nav-item"><a class="nav-link" href="#from-user-input-to-the-gpu">From user input to the GPU</a></li><li class="toc-entry nav-item"><a class="nav-link" href="#build-from-widget-to-element">Build: from Widget to Element</a></li><li class="toc-entry nav-item"><a class="nav-link" href="#layout-and-rendering">Layout and rendering</a></li></ul></li><li class="toc-entry nav-item"><a class="nav-link" href="#platform-embedding">Platform embedding</a></li><li class="toc-entry nav-item"><a class="nav-link" href="#integrating-with-other-code">Integrating with other code</a><ul class="nav"><li class="toc-entry nav-item"><a class="nav-link" href="#platform-channels">Platform channels</a></li><li class="toc-entry nav-item"><a class="nav-link" href="#foreign-function-interface-ffi">Foreign Function Interface (FFI)</a></li><li class="toc-entry nav-item"><a class="nav-link" href="#rendering-native-controls-in-a-flutter-app">Rendering native controls in a Flutter app</a></li><li class="toc-entry nav-item"><a class="nav-link" href="#hosting-flutter-content-in-a-parent-app">Hosting Flutter content in a parent app</a></li></ul></li><li class="toc-entry nav-item"><a class="nav-link" href="#flutter-web-support">Flutter web support</a></li><li class="toc-entry nav-item"><a class="nav-link" href="#further-information">Further information</a></li></ul></div><article><header class="site-content__title"><h1 id="document-title">Flutter architectural overview</h1></header><div id="site-toc--inline" class="site-toc toc-collapsible toc-collapsed"><header class="site-toc__title">Contents <span class="site-toc--inline__toggle toc-toggle-down" title="Expand table of contents"><i class="material-symbols" aria-hidden="true">keyboard_arrow_down</i></span> <span class="site-toc--inline__toggle toc-toggle-up" title="Collapse table of contents"><i class="material-symbols" aria-hidden="true">keyboard_arrow_up</i></span></header><ul class="section-nav"><li class="toc-entry"><a href="#architectural-layers">Architectural layers</a></li><li class="toc-entry"><a href="#anatomy-of-an-app">Anatomy of an app</a></li><li class="toc-entry"><a href="#reactive-user-interfaces">Reactive user interfaces</a></li><li class="toc-entry"><a href="#widgets">Widgets</a><ul><li class="toc-entry"><a href="#composition">Composition</a></li><li class="toc-entry"><a href="#building-widgets">Building widgets</a></li><li class="toc-entry"><a href="#widget-state">Widget state</a></li><li class="toc-entry"><a href="#state-management">State management</a></li></ul></li><li class="toc-entry"><a href="#rendering-and-layout">Rendering and layout</a><ul><li class="toc-entry"><a href="#flutters-rendering-model">Flutter's rendering model</a></li><li class="toc-entry"><a href="#from-user-input-to-the-gpu">From user input to the GPU</a></li><li class="toc-entry"><a href="#build-from-widget-to-element">Build: from Widget to Element</a></li><li class="toc-entry"><a href="#layout-and-rendering">Layout and rendering</a></li></ul></li><li class="toc-entry"><a href="#platform-embedding">Platform embedding</a></li><li class="toc-entry"><a href="#integrating-with-other-code">Integrating with other code</a><ul><li class="toc-entry"><a href="#platform-channels">Platform channels</a></li><li class="toc-entry"><a href="#foreign-function-interface-ffi">Foreign Function Interface (FFI)</a></li><li class="toc-entry"><a href="#rendering-native-controls-in-a-flutter-app">Rendering native controls in a Flutter app</a></li><li class="toc-entry"><a href="#hosting-flutter-content-in-a-parent-app">Hosting Flutter content in a parent app</a></li></ul></li><li class="toc-entry"><a href="#flutter-web-support">Flutter web support</a></li><li class="toc-entry"><a href="#further-information">Further information</a></li></ul><span class="site-toc--inline__toggle toc-toggle-more-items" title="Expand table of contents"><i class="material-symbols" aria-hidden="true">more_horiz</i></span></div> <?code-excerpt path-base="resources/architectural_overview/"?> <p>This article is intended to provide a high-level overview of the architecture of Flutter, including the core principles and concepts that form its design. If you are intereted in how to architect a Flutter app, check out <a href="/app-architecture">Architecting Flutter apps</a>.</p><p>Flutter is a cross-platform UI toolkit that is designed to allow code reuse across operating systems such as iOS, Android, web, and desktop, while also allowing applications to interface directly with underlying platform services. The goal is to enable developers to deliver high-performance apps that feel natural on different platforms, embracing differences where they exist while sharing as much code as possible.</p><p>During development, Flutter apps run in a VM that offers stateful hot reload of changes without needing a full recompile. (On web, Flutter supports hot restart.) For release, Flutter apps are compiled directly to machine code, whether Intel x64 or ARM instructions, or to JavaScript if targeting the web. The framework is open source, with a permissive BSD license, and has a thriving ecosystem of third-party packages that supplement the core library functionality.</p><p>This overview is divided into a number of sections:</p><ol><li>The <strong>layer model</strong>: The pieces from which Flutter is constructed.</li><li><strong>Reactive user interfaces</strong>: A core concept for Flutter user interface development.</li><li>An introduction to <strong>widgets</strong>: The fundamental building blocks of Flutter user interfaces.</li><li>The <strong>rendering process</strong>: How Flutter turns UI code into pixels.</li><li>An overview of the <strong>platform embedders</strong>: The code that lets mobile and desktop OSes execute Flutter apps.</li><li><strong>Integrating Flutter with other code</strong>: Information about different techniques available to Flutter apps.</li><li><strong>Support for the web</strong>: Concluding remarks about the characteristics of Flutter in a browser environment.</li></ol><div class="header-wrapper"><h2 id="architectural-layers">Architectural layers</h2><a class="heading-link" href="#architectural-layers" aria-label="Link to 'Architectural layers' section">#</a></div><p>Flutter is designed as an extensible, layered system. It exists as a series of independent libraries that each depend on the underlying layer. No layer has privileged access to the layer below, and every part of the framework level is designed to be optional and replaceable.</p><p><img src="/assets/images/docs/arch-overview/archdiagram.png" alt="Architectural diagram" width="100%"></p><p>To the underlying operating system, Flutter applications are packaged in the same way as any other native application. A platform-specific embedder provides an entrypoint; coordinates with the underlying operating system for access to services like rendering surfaces, accessibility, and input; and manages the message event loop. The embedder is written in a language that is appropriate for the platform: currently Java and C++ for Android, Swift and Objective-C/Objective-C++ for iOS and macOS, and C++ for Windows and Linux. Using the embedder, Flutter code can be integrated into an existing application as a module, or the code might be the entire content of the application. Flutter includes a number of embedders for common target platforms, but <a href="https://hover.build/blog/one-year-in/">other embedders also exist</a>.</p><p>At the core of Flutter is the <strong>Flutter engine</strong>, which is mostly written in C++ and supports the primitives necessary to support all Flutter applications. The engine is responsible for rasterizing composited scenes whenever a new frame needs to be painted. It provides the low-level implementation of Flutter's core API, including graphics (through <a href="/perf/impeller">Impeller</a> on iOS, Android, and desktop (behind a flag), and <a href="https://skia.org">Skia</a> on other platforms), text layout, file and network I/O, accessibility support, plugin architecture, and a Dart runtime and compile toolchain.</p><aside class="alert alert-info"><div class="alert-header"><i class="material-symbols" aria-hidden="true">info</i> <span>Note</span></div><div class="alert-content"><p>If you have a question about which devices support Impeller, check out <a href="https://flutter.dev/go/can-i-use-impeller">Can I use Impeller?</a> for detailed information.</p></div></aside><p>The engine is exposed to the Flutter framework through <a href="https://github.com/flutter/flutter/tree/main/engine/src/flutter/lib/ui"><code>dart:ui</code></a>, which wraps the underlying C++ code in Dart classes. This library exposes the lowest-level primitives, such as classes for driving input, graphics, and text rendering subsystems.</p><p>Typically, developers interact with Flutter through the <strong>Flutter framework</strong>, which provides a modern, reactive framework written in the Dart language. It includes a rich set of platform, layout, and foundational libraries, composed of a series of layers. Working from the bottom to the top, we have:</p><ul><li>Basic <strong><a href="https://api.flutter.dev/flutter/foundation/foundation-library.html">foundational</a></strong> classes, and building block services such as <strong><a href="https://api.flutter.dev/flutter/animation/animation-library.html">animation</a>, <a href="https://api.flutter.dev/flutter/painting/painting-library.html">painting</a>, and <a href="https://api.flutter.dev/flutter/gestures/gestures-library.html">gestures</a></strong> that offer commonly used abstractions over the underlying foundation.</li><li>The <strong><a href="https://api.flutter.dev/flutter/rendering/rendering-library.html">rendering layer</a></strong> provides an abstraction for dealing with layout. With this layer, you can build a tree of renderable objects. You can manipulate these objects dynamically, with the tree automatically updating the layout to reflect your changes.</li><li>The <strong><a href="https://api.flutter.dev/flutter/widgets/widgets-library.html">widgets layer</a></strong> is a composition abstraction. Each render object in the rendering layer has a corresponding class in the widgets layer. In addition, the widgets layer allows you to define combinations of classes that you can reuse. This is the layer at which the reactive programming model is introduced.</li><li>The <strong><a href="https://api.flutter.dev/flutter/material/material-library.html">Material</a></strong> and <strong><a href="https://api.flutter.dev/flutter/cupertino/cupertino-library.html">Cupertino</a></strong> libraries offer comprehensive sets of controls that use the widget layer's composition primitives to implement the Material or iOS design languages.</li></ul><p>The Flutter framework is relatively small; many higher-level features that developers might use are implemented as packages, including platform plugins like <a href="https://pub.dev/packages/camera">camera</a> and <a href="https://pub.dev/packages/webview_flutter">webview</a>, as well as platform-agnostic features like <a href="https://pub.dev/packages/characters">characters</a>, <a href="https://pub.dev/packages/http">http</a>, and <a href="https://pub.dev/packages/animations">animations</a> that build upon the core Dart and Flutter libraries. Some of these packages come from the broader ecosystem, covering services like <a href="https://pub.dev/packages/square_in_app_payments">in-app payments</a>, <a href="https://pub.dev/packages/sign_in_with_apple">Apple authentication</a>, and <a href="https://pub.dev/packages/lottie">animations</a>.</p><p>The rest of this overview broadly navigates down the layers, starting with the reactive paradigm of UI development. Then, we describe how widgets are composed together and converted into objects that can be rendered as part of an application. We describe how Flutter interoperates with other code at a platform level, before giving a brief summary of how Flutter's web support differs from other targets.</p><div class="header-wrapper"><h2 id="anatomy-of-an-app">Anatomy of an app</h2><a class="heading-link" href="#anatomy-of-an-app" aria-label="Link to 'Anatomy of an app' section">#</a></div><p>The following diagram gives an overview of the pieces that make up a regular Flutter app generated by <code>flutter create</code>. It shows where the Flutter Engine sits in this stack, highlights API boundaries, and identifies the repositories where the individual pieces live. The legend below clarifies some of the terminology commonly used to describe the pieces of a Flutter app.</p><img src="/assets/images/docs/app-anatomy.svg" alt='The layers of a Flutter app created by "flutter create": Dart app, framework, engine, embedder, runner'><p><strong>Dart App</strong></p><ul><li>Composes widgets into the desired UI.</li><li>Implements business logic.</li><li>Owned by app developer.</li></ul><p><strong>Framework</strong> (<a href="https://github.com/flutter/flutter/tree/main/packages/flutter/lib">source code</a>)</p><ul><li>Provides higher-level API to build high-quality apps (for example, widgets, hit-testing, gesture detection, accessibility, text input).</li><li>Composites the app's widget tree into a scene.</li></ul><p><strong>Engine</strong> (<a href="https://github.com/flutter/flutter/tree/main/engine/src/flutter/shell/common">source code</a>)</p><ul><li>Responsible for rasterizing composited scenes.</li><li>Provides low-level implementation of Flutter's core APIs (for example, graphics, text layout, Dart runtime).</li><li>Exposes its functionality to the framework using the <strong>dart:ui API</strong>.</li><li>Integrates with a specific platform using the Engine's <strong>Embedder API</strong>.</li></ul><p><strong>Embedder</strong> (<a href="https://github.com/flutter/flutter/tree/main/engine/src/flutter/shell/platform">source code</a>)</p><ul><li>Coordinates with the underlying operating system for access to services like rendering surfaces, accessibility, and input.</li><li>Manages the event loop.</li><li>Exposes <strong>platform-specific API</strong> to integrate the Embedder into apps.</li></ul><p><strong>Runner</strong></p><ul><li>Composes the pieces exposed by the platform-specific API of the Embedder into an app package runnable on the target platform.</li><li>Part of app template generated by <code>flutter create</code>, owned by app developer.</li></ul><div class="header-wrapper"><h2 id="reactive-user-interfaces">Reactive user interfaces</h2><a class="heading-link" href="#reactive-user-interfaces" aria-label="Link to 'Reactive user interfaces' section">#</a></div><p>On the surface, Flutter is <a href="/resources/faq#what-programming-paradigm-does-flutters-framework-use">a reactive, declarative UI framework</a>, in which the developer provides a mapping from application state to interface state, and the framework takes on the task of updating the interface at runtime when the application state changes. This model is inspired by <a href="https://www.youtube.com/watch?time_continue=2&v=x7cQ3mrcKaY&feature=emb_logo">work that came from Facebook for their own React framework</a>, which includes a rethinking of many traditional design principles.</p><p>In most traditional UI frameworks, the user interface's initial state is described once and then separately updated by user code at runtime, in response to events. One challenge of this approach is that, as the application grows in complexity, the developer needs to be aware of how state changes cascade throughout the entire UI. For example, consider the following UI:</p><p><img src="/assets/images/docs/arch-overview/color-picker.png" alt="Color picker dialog" width="66%"></p><p>There are many places where the state can be changed: the color box, the hue slider, the radio buttons. As the user interacts with the UI, changes must be reflected in every other place. Worse, unless care is taken, a minor change to one part of the user interface can cause ripple effects to seemingly unrelated pieces of code.</p><p>One solution to this is an approach like MVC, where you push data changes to the model through the controller, and then the model pushes the new state to the view through the controller. However, this also is problematic, since creating and updating UI elements are two separate steps that can easily get out of sync.</p><p>Flutter, along with other reactive frameworks, takes an alternative approach to this problem, by explicitly decoupling the user interface from its underlying state. With React-style APIs, you only create the UI description, and the framework takes care of using that one configuration to both create and/or update the user interface as appropriate.</p><p>In Flutter, widgets (akin to components in React) are represented by immutable classes that are used to configure a tree of objects. These widgets are used to manage a separate tree of objects for layout, which is then used to manage a separate tree of objects for compositing. Flutter is, at its core, a series of mechanisms for efficiently walking the modified parts of trees, converting trees of objects into lower-level trees of objects, and propagating changes across these trees.</p><p>A widget declares its user interface by overriding the <code>build()</code> method, which is a function that converts state to UI:</p><div class="code-block-wrapper language-plaintext"><div class="code-block-body"><pre class="shiki dash-light" tabindex="0"><code><span class="line"><span>UI = f(state)</span></span></code></pre></div></div><p>The <code>build()</code> method is by design fast to execute and should be free of side effects, allowing it to be called by the framework whenever needed (potentially as often as once per rendered frame).</p><p>This approach relies on certain characteristics of a language runtime (in particular, fast object instantiation and deletion). Fortunately, <a href="https://medium.com/flutter/flutter-dont-fear-the-garbage-collector-d69b3ff1ca30">Dart is particularly well suited for this task</a>.</p><div class="header-wrapper"><h2 id="widgets">Widgets</h2><a class="heading-link" href="#widgets" aria-label="Link to 'Widgets' section">#</a></div><p>As mentioned, Flutter emphasizes widgets as a unit of composition. Widgets are the building blocks of a Flutter app's user interface, and each widget is an immutable declaration of part of the user interface.</p><p>Widgets form a hierarchy based on composition. Each widget nests inside its parent and can receive context from the parent. This structure carries all the way up to the root widget (the container that hosts the Flutter app, typically <code>MaterialApp</code> or <code>CupertinoApp</code>), as this trivial example shows:</p> <?code-excerpt "lib/main.dart (main)"?> <div class="code-block-wrapper language-dart"><div class="code-block-body"><span class="code-block-language" title="Language dart">dart</span><pre class="shiki dash-light" tabindex="0"><code><span class="line"><span style="color:#BD2314">import</span><span style="color:#0C7064"> 'package:flutter/material.dart'</span><span style="color:#222222">;</span></span> <span class="line"><span style="color:#BD2314">import</span><span style="color:#0C7064"> 'package:flutter/services.dart'</span><span style="color:#222222">;</span></span> <span class="line"></span> <span class="line"><span style="color:#BD2314">void</span><span style="color:#6200EE"> main</span><span style="color:#222222">() => </span><span style="color:#6200EE">runApp</span><span style="color:#222222">(</span><span style="color:#BD2314">const</span><span style="color:#0468D7"> MyApp</span><span style="color:#222222">());</span></span> <span class="line"></span> <span class="line"><span style="color:#BD2314">class</span><span style="color:#0468D7"> MyApp</span><span style="color:#BD2314"> extends</span><span style="color:#0468D7"> StatelessWidget</span><span style="color:#222222"> {</span></span> <span class="line"><span style="color:#BD2314"> const</span><span style="color:#0468D7"> MyApp</span><span style="color:#222222">({</span><span style="color:#BD2314">super</span><span style="color:#222222">.key});</span></span> <span class="line"></span> <span class="line"><span style="color:#BD2314"> @override</span></span> <span class="line"><span style="color:#0468D7"> Widget</span><span style="color:#6200EE"> build</span><span style="color:#222222">(</span><span style="color:#0468D7">BuildContext</span><span style="color:#222222"> context) {</span></span> <span class="line"><span style="color:#BD2314"> return</span><span style="color:#0468D7"> MaterialApp</span><span style="color:#222222">(</span></span> <span class="line"><span style="color:#222222"> home: </span><span style="color:#0468D7">Scaffold</span><span style="color:#222222">(</span></span> <span class="line"><span style="color:#222222"> appBar: </span><span style="color:#0468D7">AppBar</span><span style="color:#222222">(title: </span><span style="color:#BD2314">const</span><span style="color:#0468D7"> Text</span><span style="color:#222222">(</span><span style="color:#0C7064">'My Home Page'</span><span style="color:#222222">)),</span></span> <span class="line"><span style="color:#222222"> body: </span><span style="color:#0468D7">Center</span><span style="color:#222222">(</span></span> <span class="line"><span style="color:#222222"> child: </span><span style="color:#0468D7">Builder</span><span style="color:#222222">(</span></span> <span class="line"><span style="color:#222222"> builder: (context) {</span></span> <span class="line"><span style="color:#BD2314"> return</span><span style="color:#0468D7"> Column</span><span style="color:#222222">(</span></span> <span class="line"><span style="color:#222222"> children: [</span></span> <span class="line"><span style="color:#BD2314"> const</span><span style="color:#0468D7"> Text</span><span style="color:#222222">(</span><span style="color:#0C7064">'Hello World'</span><span style="color:#222222">),</span></span> <span class="line"><span style="color:#BD2314"> const</span><span style="color:#0468D7"> SizedBox</span><span style="color:#222222">(height: </span><span style="color:#0C7064">20</span><span style="color:#222222">),</span></span> <span class="line"><span style="color:#0468D7"> ElevatedButton</span><span style="color:#222222">(</span></span> <span class="line"><span style="color:#222222"> onPressed: () {</span></span> <span class="line"><span style="color:#6200EE"> print</span><span style="color:#222222">(</span><span style="color:#0C7064">'Click!'</span><span style="color:#222222">);</span></span> <span class="line"><span style="color:#222222"> },</span></span> <span class="line"><span style="color:#222222"> child: </span><span style="color:#BD2314">const</span><span style="color:#0468D7"> Text</span><span style="color:#222222">(</span><span style="color:#0C7064">'A button'</span><span style="color:#222222">),</span></span> <span class="line"><span style="color:#222222"> ),</span></span> <span class="line"><span style="color:#222222"> ],</span></span> <span class="line"><span style="color:#222222"> );</span></span> <span class="line"><span style="color:#222222"> },</span></span> <span class="line"><span style="color:#222222"> ),</span></span> <span class="line"><span style="color:#222222"> ),</span></span> <span class="line"><span style="color:#222222"> ),</span></span> <span class="line"><span style="color:#222222"> );</span></span> <span class="line"><span style="color:#222222"> }</span></span> <span class="line"><span style="color:#222222">}</span></span></code></pre></div></div><p>In the preceding code, all instantiated classes are widgets.</p><p>Apps update their user interface in response to events (such as a user interaction) by telling the framework to replace a widget in the hierarchy with another widget. The framework then compares the new and old widgets, and efficiently updates the user interface.</p><p>Flutter has its own implementations of each UI control, rather than deferring to those provided by the system: for example, there is a pure <a href="https://api.flutter.dev/flutter/cupertino/CupertinoSwitch-class.html">Dart implementation</a> of both the <a href="https://developer.apple.com/design/human-interface-guidelines/toggles">iOS Toggle control</a> and the <a href="https://api.flutter.dev/flutter/material/Switch-class.html">one for</a> the <a href="https://m3.material.io/components/switch">Android equivalent</a>.</p><p>This approach provides several benefits:</p><ul><li>Provides for unlimited extensibility. A developer who wants a variant of the Switch control can create one in any arbitrary way, and is not limited to the extension points provided by the OS.</li><li>Avoids a significant performance bottleneck by allowing Flutter to composite the entire scene at once, without transitioning back and forth between Flutter code and platform code.</li><li>Decouples the application behavior from any operating system dependencies. The application looks and feels the same on all versions of the OS, even if the OS changed the implementations of its controls.</li></ul><div class="header-wrapper"><h3 id="composition">Composition</h3><a class="heading-link" href="#composition" aria-label="Link to 'Composition' section">#</a></div><p>Widgets are typically composed of many other small, single-purpose widgets that combine to produce powerful effects.</p><p>Where possible, the number of design concepts is kept to a minimum while allowing the total vocabulary to be large. For example, in the widgets layer, Flutter uses the same core concept (a <code>Widget</code>) to represent drawing to the screen, layout (positioning and sizing), user interactivity, state management, theming, animations, and navigation. In the animation layer, a pair of concepts, <code>Animation</code>s and <code>Tween</code>s, cover most of the design space. In the rendering layer, <code>RenderObject</code>s are used to describe layout, painting, hit testing, and accessibility. In each of these cases, the corresponding vocabulary ends up being large: there are hundreds of widgets and render objects, and dozens of animation and tween types.</p><p>The class hierarchy is deliberately shallow and broad to maximize the possible number of combinations, focusing on small, composable widgets that each do one thing well. Core features are abstract, with even basic features like padding and alignment being implemented as separate components rather than being built into the core. (This also contrasts with more traditional APIs where features like padding are built in to the common core of every layout component.) So, for example, to center a widget, rather than adjusting a notional <code>Align</code> property, you wrap it in a <a href="https://api.flutter.dev/flutter/widgets/Center-class.html"><code>Center</code></a> widget.</p><p>There are widgets for padding, alignment, rows, columns, and grids. These layout widgets do not have a visual representation of their own. Instead, their sole purpose is to control some aspect of another widget's layout. Flutter also includes utility widgets that take advantage of this compositional approach.</p><p>For example, <a href="https://api.flutter.dev/flutter/widgets/Container-class.html"><code>Container</code></a>, a commonly used widget, is made up of several widgets responsible for layout, painting, positioning, and sizing. Specifically, <code>Container</code> is made up of the <a href="https://api.flutter.dev/flutter/widgets/LimitedBox-class.html"><code>LimitedBox</code></a>, <a href="https://api.flutter.dev/flutter/widgets/ConstrainedBox-class.html"><code>ConstrainedBox</code></a>, <a href="https://api.flutter.dev/flutter/widgets/Align-class.html"><code>Align</code></a>, <a href="https://api.flutter.dev/flutter/widgets/Padding-class.html"><code>Padding</code></a>, <a href="https://api.flutter.dev/flutter/widgets/DecoratedBox-class.html"><code>DecoratedBox</code></a>, and <a href="https://api.flutter.dev/flutter/widgets/Transform-class.html"><code>Transform</code></a> widgets, as you can see by reading its source code. A defining characteristic of Flutter is that you can drill down into the source for any widget and examine it. So, rather than subclassing <code>Container</code> to produce a customized effect, you can compose it and other widgets in novel ways, or just create a new widget using <code>Container</code> as inspiration.</p><div class="header-wrapper"><h3 id="building-widgets">Building widgets</h3><a class="heading-link" href="#building-widgets" aria-label="Link to 'Building widgets' section">#</a></div><p>As mentioned earlier, you determine the visual representation of a widget by overriding the <a href="https://api.flutter.dev/flutter/widgets/StatelessWidget/build.html"><code>build()</code></a> function to return a new element tree. This tree represents the widget's part of the user interface in more concrete terms. For example, a toolbar widget might have a build function that returns a <a href="https://api.flutter.dev/flutter/widgets/Row-class.html">horizontal layout</a> of some <a href="https://api.flutter.dev/flutter/widgets/Text-class.html">text</a> and <a href="https://api.flutter.dev/flutter/material/IconButton-class.html">various</a> <a href="https://api.flutter.dev/flutter/material/PopupMenuButton-class.html">buttons</a>. As needed, the framework recursively asks each widget to build until the tree is entirely described by <a href="https://api.flutter.dev/flutter/widgets/RenderObjectWidget-class.html">concrete renderable objects</a>. The framework then stitches together the renderable objects into a renderable object tree.</p><p>A widget's build function should be free of side effects. Whenever the function is asked to build, the widget should return a new tree of widgets<sup class="footnote-ref"><a href="#fn1" id="fnref1">[1]</a></sup>, regardless of what the widget previously returned. The framework does the heavy lifting work to determine which build methods need to be called based on the render object tree (described in more detail later). More information about this process can be found in the <a href="/resources/inside-flutter#linear-reconciliation">Inside Flutter topic</a>.</p><p>On each rendered frame, Flutter can recreate just the parts of the UI where the state has changed by calling that widget's <code>build()</code> method. Therefore it is important that build methods should return quickly, and heavy computational work should be done in some asynchronous manner and then stored as part of the state to be used by a build method.</p><p>While relatively naive in approach, this automated comparison is quite effective, enabling high-performance, interactive apps. And, the design of the build function simplifies your code by focusing on declaring what a widget is made of, rather than the complexities of updating the user interface from one state to another.</p><div class="header-wrapper"><h3 id="widget-state">Widget state</h3><a class="heading-link" href="#widget-state" aria-label="Link to 'Widget state' section">#</a></div><p>The framework introduces two major classes of widget: <em>stateful</em> and <em>stateless</em> widgets.</p><p>Many widgets have no mutable state: they don't have any properties that change over time (for example, an icon or a label). These widgets subclass <a href="https://api.flutter.dev/flutter/widgets/StatelessWidget-class.html"><code>StatelessWidget</code></a>.</p><p>However, if the unique characteristics of a widget needs to change based on user interaction or other factors, that widget is <em>stateful</em>. For example, if a widget has a counter that increments whenever the user taps a button, then the value of the counter is the state for that widget. When that value changes, the widget needs to be rebuilt to update its part of the UI. These widgets subclass <a href="https://api.flutter.dev/flutter/widgets/StatefulWidget-class.html"><code>StatefulWidget</code></a>, and (because the widget itself is immutable) they store mutable state in a separate class that subclasses <a href="https://api.flutter.dev/flutter/widgets/State-class.html"><code>State</code></a>. <code>StatefulWidget</code>s don't have a build method; instead, their user interface is built through their <code>State</code> object.</p><p>Whenever you mutate a <code>State</code> object (for example, by incrementing the counter), you must call <a href="https://api.flutter.dev/flutter/widgets/State/setState.html"><code>setState()</code></a> to signal the framework to update the user interface by calling the <code>State</code>'s build method again.</p><p>Having separate state and widget objects lets other widgets treat both stateless and stateful widgets in exactly the same way, without being concerned about losing state. Instead of needing to hold on to a child to preserve its state, the parent can create a new instance of the child at any time without losing the child's persistent state. The framework does all the work of finding and reusing existing state objects when appropriate.</p><div class="header-wrapper"><h3 id="state-management">State management</h3><a class="heading-link" href="#state-management" aria-label="Link to 'State management' section">#</a></div><p>So, if many widgets can contain state, how is state managed and passed around the system?</p><p>As with any other class, you can use a constructor in a widget to initialize its data, so a <code>build()</code> method can ensure that any child widget is instantiated with the data it needs:</p><div class="code-block-wrapper language-dart"><div class="code-block-body"><span class="code-block-language" title="Language dart">dart</span><pre class="shiki dash-light" tabindex="0"><code><span class="line"><span style="color:#BD2314">@override</span></span> <span class="line"><span style="color:#0468D7">Widget</span><span style="color:#6200EE"> build</span><span style="color:#222222">(</span><span style="color:#0468D7">BuildContext</span><span style="color:#222222"> context) {</span></span> <span class="line"><span style="color:#BD2314"> return</span><span style="color:#0468D7"> ContentWidget</span><span style="color:#222222">(</span><mark class="highlight"><span style="color:#222222">importantState</span></mark><span style="color:#222222">);</span></span> <span class="line"><span style="color:#222222">}</span></span></code></pre></div></div><p>Where <code>importantState</code> is a placeholder for the class that contains the state important to the <code>Widget</code>.</p><p>As widget trees get deeper, however, passing state information up and down the tree hierarchy becomes cumbersome. So, a third widget type, <a href="https://api.flutter.dev/flutter/widgets/InheritedWidget-class.html"><code>InheritedWidget</code></a>, provides an easy way to grab data from a shared ancestor. You can use <code>InheritedWidget</code> to create a state widget that wraps a common ancestor in the widget tree, as shown in this example:</p><p><img src="/assets/images/docs/arch-overview/inherited-widget.png" alt="Inherited widgets" width="50%"></p><p>Whenever one of the <code>ExamWidget</code> or <code>GradeWidget</code> objects needs data from <code>StudentState</code>, it can now access it with a command such as:</p><div class="code-block-wrapper language-dart"><div class="code-block-body"><span class="code-block-language" title="Language dart">dart</span><pre class="shiki dash-light" tabindex="0"><code><span class="line"><span style="color:#BD2314">final</span><span style="color:#222222"> studentState = </span><span style="color:#0468D7">StudentState</span><span style="color:#222222">.</span><span style="color:#6200EE">of</span><span style="color:#222222">(context);</span></span></code></pre></div></div><p>The <code>of(context)</code> call takes the build context (a handle to the current widget location), and returns <a href="https://api.flutter.dev/flutter/widgets/BuildContext/dependOnInheritedWidgetOfExactType.html">the nearest ancestor in the tree</a> that matches the <code>StudentState</code> type. <code>InheritedWidget</code>s also offer an <code>updateShouldNotify()</code> method, which Flutter calls to determine whether a state change should trigger a rebuild of child widgets that use it.</p><p>Flutter itself uses <code>InheritedWidget</code> extensively as part of the framework for shared state, such as the application's <em>visual theme</em>, which includes <a href="https://api.flutter.dev/flutter/material/ThemeData-class.html">properties like color and type styles</a> that are pervasive throughout an application. The <code>MaterialApp</code> <code>build()</code> method inserts a theme in the tree when it builds, and then deeper in the hierarchy a widget can use the <code>.of()</code> method to look up the relevant theme data.</p><p>For example:</p> <?code-excerpt "lib/main.dart (container)"?> <div class="code-block-wrapper language-dart"><div class="code-block-body"><span class="code-block-language" title="Language dart">dart</span><pre class="shiki dash-light" tabindex="0"><code><span class="line"><span style="color:#0468D7">Container</span><span style="color:#222222">(</span></span> <span class="line"><span style="color:#222222"> color: </span><span style="color:#0468D7">Theme</span><span style="color:#222222">.</span><span style="color:#6200EE">of</span><span style="color:#222222">(context).secondaryHeaderColor,</span></span> <span class="line"><span style="color:#222222"> child: </span><span style="color:#0468D7">Text</span><span style="color:#222222">(</span></span> <span class="line"><span style="color:#0C7064"> 'Text with a background color'</span><span style="color:#222222">,</span></span> <span class="line"><span style="color:#222222"> style: </span><span style="color:#0468D7">Theme</span><span style="color:#222222">.</span><span style="color:#6200EE">of</span><span style="color:#222222">(context).textTheme.titleLarge,</span></span> <span class="line"><span style="color:#222222"> ),</span></span> <span class="line"><span style="color:#222222">);</span></span></code></pre></div></div><p>As applications grow, more advanced state management approaches that reduce the ceremony of creating and using stateful widgets become more attractive. Many Flutter apps use utility packages like <a href="https://pub.dev/packages/provider">provider</a>, which provides a wrapper around <code>InheritedWidget</code>. Flutter's layered architecture also enables alternative approaches to implement the transformation of state into UI, such as the <a href="https://pub.dev/packages/flutter_hooks">flutter_hooks</a> package.</p><div class="header-wrapper"><h2 id="rendering-and-layout">Rendering and layout</h2><a class="heading-link" href="#rendering-and-layout" aria-label="Link to 'Rendering and layout' section">#</a></div><p>This section describes the rendering pipeline, which is the series of steps that Flutter takes to convert a hierarchy of widgets into the actual pixels painted onto a screen.</p><div class="header-wrapper"><h3 id="flutters-rendering-model">Flutter's rendering model</h3><a class="heading-link" href="#flutters-rendering-model" aria-label="Link to 'Flutter's rendering model' section">#</a></div><p>You might be wondering: if Flutter is a cross-platform framework, then how can it offer comparable performance to single-platform frameworks?</p><p>It's useful to start by thinking about how traditional Android apps work. When drawing, you first call the Java code of the Android framework. The Android system libraries provide the components responsible for drawing themselves to a <code>Canvas</code> object, which Android can then render with <a href="https://skia.org">Skia</a>, a graphics engine written in C/C++ that calls the CPU or GPU to complete the drawing on the device.</p><p>Cross-platform frameworks <em>typically</em> work by creating an abstraction layer over the underlying native Android and iOS UI libraries, attempting to smooth out the inconsistencies of each platform representation. App code is often written in an interpreted language like JavaScript, which must in turn interact with the Java-based Android or Objective-C-based iOS system libraries to display UI. All this adds overhead that can be significant, particularly where there is a lot of interaction between the UI and the app logic.</p><p>By contrast, Flutter minimizes those abstractions, bypassing the system UI widget libraries in favor of its own widget set. The Dart code that paints Flutter's visuals is compiled into native code, which uses Impeller for rendering. Impeller is shipped along with the application, allowing the developer to upgrade their app to stay updated with the latest performance improvements even if the phone hasn't been updated with a new Android version. The same is true for Flutter on other native platforms, such as Windows or macOS.</p><aside class="alert alert-info"><div class="alert-header"><i class="material-symbols" aria-hidden="true">info</i> <span>Note</span></div><div class="alert-content"><p>If you want to know which devices Impeller supports, check out <a href="https://flutter.dev/go/can-i-use-impeller">Can I use Impeller?</a>. For more information, visit <a href="/perf/impeller">Impeller rendering engine</a></p></div></aside><div class="header-wrapper"><h3 id="from-user-input-to-the-gpu">From user input to the GPU</h3><a class="heading-link" href="#from-user-input-to-the-gpu" aria-label="Link to 'From user input to the GPU' section">#</a></div><p>The overriding principle that Flutter applies to its rendering pipeline is that <strong>simple is fast</strong>. Flutter has a straightforward pipeline for how data flows to the system, as shown in the following sequencing diagram:</p><p><img src="/assets/images/docs/arch-overview/render-pipeline.png" alt="Render pipeline sequencing diagram" width="100%"></p><p>Let's take a look at some of these phases in greater detail.</p><div class="header-wrapper"><h3 id="build-from-widget-to-element">Build: from Widget to Element</h3><a class="heading-link" href="#build-from-widget-to-element" aria-label="Link to 'Build: from Widget to Element' section">#</a></div><p>Consider this code fragment that demonstrates a widget hierarchy:</p> <?code-excerpt "lib/main.dart (widget-hierarchy)"?> <div class="code-block-wrapper language-dart"><div class="code-block-body"><span class="code-block-language" title="Language dart">dart</span><pre class="shiki dash-light" tabindex="0"><code><span class="line"><span style="color:#0468D7">Container</span><span style="color:#222222">(</span></span> <span class="line"><span style="color:#222222"> color: </span><span style="color:#0468D7">Colors</span><span style="color:#222222">.blue,</span></span> <span class="line"><span style="color:#222222"> child: </span><span style="color:#0468D7">Row</span><span style="color:#222222">(</span></span> <span class="line"><span style="color:#222222"> children: [</span></span> <span class="line"><span style="color:#0468D7"> Image</span><span style="color:#222222">.</span><span style="color:#6200EE">network</span><span style="color:#222222">(</span><span style="color:#0C7064">'https://www.example.com/1.png'</span><span style="color:#222222">),</span></span> <span class="line"><span style="color:#BD2314"> const</span><span style="color:#0468D7"> Text</span><span style="color:#222222">(</span><span style="color:#0C7064">'A'</span><span style="color:#222222">),</span></span> <span class="line"><span style="color:#222222"> ],</span></span> <span class="line"><span style="color:#222222"> ),</span></span> <span class="line"><span style="color:#222222">);</span></span></code></pre></div></div><p>When Flutter needs to render this fragment, it calls the <code>build()</code> method, which returns a subtree of widgets that renders UI-based on the current app state. During this process, the <code>build()</code> method can introduce new widgets, as necessary, based on its state. As an example, in the preceding code fragment, <code>Container</code> has <code>color</code> and <code>child</code> properties. From looking at the <a href="https://github.com/flutter/flutter/blob/02efffc134ab4ce4ff50a9ddd86c832efdb80462/packages/flutter/lib/src/widgets/container.dart#L401">source code</a> for <code>Container</code>, you can see that if the color is not null, it inserts a <code>ColoredBox</code> representing the color:</p><div class="code-block-wrapper language-dart"><div class="code-block-body"><span class="code-block-language" title="Language dart">dart</span><pre class="shiki dash-light" tabindex="0"><code><span class="line"><span style="color:#BD2314">if</span><span style="color:#222222"> (color != </span><span style="color:#0C7064">null</span><span style="color:#222222">)</span></span> <span class="line"><span style="color:#222222"> current = </span><span style="color:#0468D7">ColoredBox</span><span style="color:#222222">(color: color!, child: current);</span></span></code></pre></div></div><p>Correspondingly, the <code>Image</code> and <code>Text</code> widgets might insert child widgets such as <code>RawImage</code> and <code>RichText</code> during the build process. The eventual widget hierarchy might therefore be deeper than what the code represents, as in this case<sup class="footnote-ref"><a href="#fn2" id="fnref2">[2]</a></sup>:</p><p><img src="/assets/images/docs/arch-overview/widgets.png" alt="Render pipeline sequencing diagram" width="35%"></p><p>This explains why, when you examine the tree through a debug tool such as the <a href="/tools/devtools/inspector">Flutter inspector</a>, part of the Flutter/Dart DevTools, you might see a structure that is considerably deeper than what is in your original code.</p><p>During the build phase, Flutter translates the widgets expressed in code into a corresponding <strong>element tree</strong>, with one element for every widget. Each element represents a specific instance of a widget in a given location of the tree hierarchy. There are two basic types of elements:</p><ul><li><code>ComponentElement</code>, a host for other elements.</li><li><code>RenderObjectElement</code>, an element that participates in the layout or paint phases.</li></ul><p><img src="/assets/images/docs/arch-overview/widget-element.png" alt="Render pipeline sequencing diagram" width="85%"></p><p><code>RenderObjectElement</code>s are an intermediary between their widget analog and the underlying <code>RenderObject</code>, which we'll come to later.</p><p>The element for any widget can be referenced through its <code>BuildContext</code>, which is a handle to the location of a widget in the tree. This is the <code>context</code> in a function call such as <code>Theme.of(context)</code>, and is supplied to the <code>build()</code> method as a parameter.</p><p>Because widgets are immutable, including the parent/child relationship between nodes, any change to the widget tree (such as changing <code>Text('A')</code> to <code>Text('B')</code> in the preceding example) causes a new set of widget objects to be returned. But that doesn't mean the underlying representation must be rebuilt. The element tree is persistent from frame to frame, and therefore plays a critical performance role, allowing Flutter to act as if the widget hierarchy is fully disposable while caching its underlying representation. By only walking through the widgets that changed, Flutter can rebuild just the parts of the element tree that require reconfiguration.</p><div class="header-wrapper"><h3 id="layout-and-rendering">Layout and rendering</h3><a class="heading-link" href="#layout-and-rendering" aria-label="Link to 'Layout and rendering' section">#</a></div><p>It would be a rare application that drew only a single widget. An important part of any UI framework is therefore the ability to efficiently lay out a hierarchy of widgets, determining the size and position of each element before they are rendered on the screen.</p><p>The base class for every node in the render tree is <a href="https://api.flutter.dev/flutter/rendering/RenderObject-class.html"><code>RenderObject</code></a>, which defines an abstract model for layout and painting. This is extremely general: it does not commit to a fixed number of dimensions or even a Cartesian coordinate system (demonstrated by <a href="https://dartpad.dev/?id=596b1d6331e3b9d7b00420085fab3e27">this example of a polar coordinate system</a>). Each <code>RenderObject</code> knows its parent, but knows little about its children other than how to <em>visit</em> them and their constraints. This provides <code>RenderObject</code> with sufficient abstraction to be able to handle a variety of use cases.</p><p>During the build phase, Flutter creates or updates an object that inherits from <code>RenderObject</code> for each <code>RenderObjectElement</code> in the element tree. <code>RenderObject</code>s are primitives: <a href="https://api.flutter.dev/flutter/rendering/RenderParagraph-class.html"><code>RenderParagraph</code></a> renders text, <a href="https://api.flutter.dev/flutter/rendering/RenderImage-class.html"><code>RenderImage</code></a> renders an image, and <a href="https://api.flutter.dev/flutter/rendering/RenderTransform-class.html"><code>RenderTransform</code></a> applies a transformation before painting its child.</p><p><img src="/assets/images/docs/arch-overview/trees.png" alt="Differences between the widgets hierarchy and the element and render trees" width="100%"></p><p>Most Flutter widgets are rendered by an object that inherits from the <code>RenderBox</code> subclass, which represents a <code>RenderObject</code> of fixed size in a 2D Cartesian space. <code>RenderBox</code> provides the basis of a <em>box constraint model</em>, establishing a minimum and maximum width and height for each widget to be rendered.</p><p>To perform layout, Flutter walks the render tree in a depth-first traversal and <strong>passes down size constraints</strong> from parent to child. In determining its size, the child <em>must</em> respect the constraints given to it by its parent. Children respond by <strong>passing up a size</strong> to their parent object within the constraints the parent established.</p><p><img src="/assets/images/docs/arch-overview/constraints-sizes.png" alt="Constraints go down, sizes go up" width="80%"></p><p>At the end of this single walk through the tree, every object has a defined size within its parent's constraints and is ready to be painted by calling the <a href="https://api.flutter.dev/flutter/rendering/RenderObject/paint.html"><code>paint()</code></a> method.</p><p>The box constraint model is very powerful as a way to layout objects in <em>O(n)</em> time:</p><ul><li>Parents can dictate the size of a child object by setting maximum and minimum constraints to the same value. For example, the topmost render object in a phone app constrains its child to be the size of the screen. (Children can choose how to use that space. For example, they might just center what they want to render within the dictated constraints.)</li><li>A parent can dictate the child's width but give the child flexibility over height (or dictate height but offer flexibility over width). A real-world example is flow text, which might have to fit a horizontal constraint but vary vertically depending on the quantity of text.</li></ul><p>This model works even when a child object needs to know how much space it has available to decide how it will render its content. By using a <a href="https://api.flutter.dev/flutter/widgets/LayoutBuilder-class.html"><code>LayoutBuilder</code></a> widget, the child object can examine the passed-down constraints and use those to determine how it will use them, for example:</p> <?code-excerpt "lib/main.dart (layout-builder)"?> <div class="code-block-wrapper language-dart"><div class="code-block-body"><span class="code-block-language" title="Language dart">dart</span><pre class="shiki dash-light" tabindex="0"><code><span class="line"><span style="color:#0468D7">Widget</span><span style="color:#6200EE"> build</span><span style="color:#222222">(</span><span style="color:#0468D7">BuildContext</span><span style="color:#222222"> context) {</span></span> <span class="line"><span style="color:#BD2314"> return</span><span style="color:#0468D7"> LayoutBuilder</span><span style="color:#222222">(</span></span> <span class="line"><span style="color:#222222"> builder: (context, constraints) {</span></span> <span class="line"><span style="color:#BD2314"> if</span><span style="color:#222222"> (constraints.maxWidth < </span><span style="color:#0C7064">600</span><span style="color:#222222">) {</span></span> <span class="line"><span style="color:#BD2314"> return</span><span style="color:#BD2314"> const</span><span style="color:#0468D7"> OneColumnLayout</span><span style="color:#222222">();</span></span> <span class="line"><span style="color:#222222"> } </span><span style="color:#BD2314">else</span><span style="color:#222222"> {</span></span> <span class="line"><span style="color:#BD2314"> return</span><span style="color:#BD2314"> const</span><span style="color:#0468D7"> TwoColumnLayout</span><span style="color:#222222">();</span></span> <span class="line"><span style="color:#222222"> }</span></span> <span class="line"><span style="color:#222222"> },</span></span> <span class="line"><span style="color:#222222"> );</span></span> <span class="line"><span style="color:#222222">}</span></span></code></pre></div></div><p>More information about the constraint and layout system, along with working examples, can be found in the <a href="/ui/layout/constraints">Understanding constraints</a> topic.</p><p>The root of all <code>RenderObject</code>s is the <code>RenderView</code>, which represents the total output of the render tree. When the platform demands a new frame to be rendered (for example, because of a <a href="https://source.android.com/devices/graphics/implement-vsync">vsync</a> or because a texture decompression/upload is complete), a call is made to the <code>compositeFrame()</code> method, which is part of the <code>RenderView</code> object at the root of the render tree. This creates a <code>SceneBuilder</code> to trigger an update of the scene. When the scene is complete, the <code>RenderView</code> object passes the composited scene to the <code>Window.render()</code> method in <code>dart:ui</code>, which passes control to the GPU to render it.</p><p>Further details of the composition and rasterization stages of the pipeline are beyond the scope of this high-level article, but more information can be found <a href="https://www.youtube.com/watch?v=UUfXWzp0-DU">in this talk on the Flutter rendering pipeline</a>.</p><div class="header-wrapper"><h2 id="platform-embedding">Platform embedding</h2><a class="heading-link" href="#platform-embedding" aria-label="Link to 'Platform embedding' section">#</a></div><p>As we've seen, rather than being translated into the equivalent OS widgets, Flutter user interfaces are built, laid out, composited, and painted by Flutter itself. The mechanism for obtaining the texture and participating in the app lifecycle of the underlying operating system inevitably varies depending on the unique concerns of that platform. The engine is platform-agnostic, presenting a <a href="https://github.com/flutter/flutter/blob/main/engine/src/flutter/shell/platform/embedder/embedder.h">stable ABI (Application Binary Interface)</a> that provides a <em>platform embedder</em> with a way to set up and use Flutter.</p><p>The platform embedder is the native OS application that hosts all Flutter content, and acts as the glue between the host operating system and Flutter. When you start a Flutter app, the embedder provides the entrypoint, initializes the Flutter engine, obtains threads for UI and rastering, and creates a texture that Flutter can write to. The embedder is also responsible for the app lifecycle, including input gestures (such as mouse, keyboard, touch), window sizing, thread management, and platform messages. Flutter includes platform embedders for Android, iOS, Windows, macOS, and Linux; you can also create a custom platform embedder, as in <a href="https://github.com/chinmaygarde/fluttercast">this worked example</a> that supports remoting Flutter sessions through a VNC-style framebuffer or <a href="https://github.com/ardera/flutter-pi">this worked example for Raspberry Pi</a>.</p><p>Each platform has its own set of APIs and constraints. Some brief platform-specific notes:</p><ul><li>On iOS and macOS, Flutter is loaded into the embedder as a <code>UIViewController</code> or <code>NSViewController</code>, respectively. The platform embedder creates a <code>FlutterEngine</code>, which serves as a host to the Dart VM and your Flutter runtime, and a <code>FlutterViewController</code>, which attaches to the <code>FlutterEngine</code> to pass UIKit or Cocoa input events into Flutter and to display frames rendered by the <code>FlutterEngine</code> using Metal or OpenGL.</li><li>On Android, Flutter is, by default, loaded into the embedder as an <code>Activity</code>. The view is controlled by a <a href="https://api.flutter.dev/javadoc/io/flutter/embedding/android/FlutterView.html"><code>FlutterView</code></a>, which renders Flutter content either as a view or a texture, depending on the composition and z-ordering requirements of the Flutter content.</li><li>On Windows, Flutter is hosted in a traditional Win32 app, and content is rendered using <a href="https://chromium.googlesource.com/angle/angle/+/master/README.md">ANGLE</a>, a library that translates OpenGL API calls to the DirectX 11 equivalents.</li></ul><div class="header-wrapper"><h2 id="integrating-with-other-code">Integrating with other code</h2><a class="heading-link" href="#integrating-with-other-code" aria-label="Link to 'Integrating with other code' section">#</a></div><p>Flutter provides a variety of interoperability mechanisms, whether you're accessing code or APIs written in a language like Kotlin or Swift, calling a native C-based API, embedding native controls in a Flutter app, or embedding Flutter in an existing application.</p><div class="header-wrapper"><h3 id="platform-channels">Platform channels</h3><a class="heading-link" href="#platform-channels" aria-label="Link to 'Platform channels' section">#</a></div><p>For mobile and desktop apps, Flutter allows you to call into custom code through a <em>platform channel</em>, which is a mechanism for communicating between your Dart code and the platform-specific code of your host app. By creating a common channel (encapsulating a name and a codec), you can send and receive messages between Dart and a platform component written in a language like Kotlin or Swift. Data is serialized from a Dart type like <code>Map</code> into a standard format, and then deserialized into an equivalent representation in Kotlin (such as <code>HashMap</code>) or Swift (such as <code>Dictionary</code>).</p><p><img src="/assets/images/docs/arch-overview/platform-channels.png" alt="How platform channels allow Flutter to communicate with host code" width="70%"></p><p>The following is a short platform channel example of a Dart call to a receiving event handler in Kotlin (Android) or Swift (iOS):</p> <?code-excerpt "lib/main.dart (method-channel)"?> <div class="code-block-wrapper language-dart"><div class="code-block-body"><span class="code-block-language" title="Language dart">dart</span><pre class="shiki dash-light" tabindex="0"><code><span class="line"><span style="color:#6E6E70">// Dart side</span></span> <span class="line"><span style="color:#BD2314">const</span><span style="color:#222222"> channel = </span><span style="color:#0468D7">MethodChannel</span><span style="color:#222222">(</span><span style="color:#0C7064">'foo'</span><span style="color:#222222">);</span></span> <span class="line"><span style="color:#BD2314">final</span><span style="color:#222222"> greeting = </span><span style="color:#BD2314">await</span><span style="color:#222222"> channel.</span><span style="color:#6200EE">invokeMethod</span><span style="color:#222222">(</span><span style="color:#0C7064">'bar'</span><span style="color:#222222">, </span><span style="color:#0C7064">'world'</span><span style="color:#222222">) </span><span style="color:#BD2314">as</span><span style="color:#0468D7"> String</span><span style="color:#222222">;</span></span> <span class="line"><span style="color:#6200EE">print</span><span style="color:#222222">(greeting);</span></span></code></pre></div></div><div class="code-block-wrapper language-kotlin"><div class="code-block-body"><span class="code-block-language" title="Language kotlin">kotlin</span><pre class="shiki dash-light" tabindex="0"><code><span class="line"><span style="color:#6E6E70">// Android (Kotlin)</span></span> <span class="line"><span style="color:#BD2314">val</span><span style="color:#222222"> channel = </span><span style="color:#6200EE">MethodChannel</span><span style="color:#222222">(flutterView, </span><span style="color:#0C7064">"foo"</span><span style="color:#222222">)</span></span> <span class="line"><span style="color:#222222">channel.</span><span style="color:#6200EE">setMethodCallHandler</span><span style="color:#222222"> { call, result </span><span style="color:#BD2314">-></span></span> <span class="line"><span style="color:#BD2314"> when</span><span style="color:#222222"> (call.method) {</span></span> <span class="line"><span style="color:#0C7064"> "bar"</span><span style="color:#BD2314"> -></span><span style="color:#222222"> result.</span><span style="color:#6200EE">success</span><span style="color:#222222">(</span><span style="color:#0C7064">"Hello, </span><span style="color:#222222">${</span><span style="color:#0C7064">call.arguments</span><span style="color:#222222">}</span><span style="color:#0C7064">"</span><span style="color:#222222">)</span></span> <span class="line"><span style="color:#BD2314"> else</span><span style="color:#BD2314"> -></span><span style="color:#222222"> result.</span><span style="color:#6200EE">notImplemented</span><span style="color:#222222">()</span></span> <span class="line"><span style="color:#222222"> }</span></span> <span class="line"><span style="color:#222222">}</span></span></code></pre></div></div><div class="code-block-wrapper language-swift"><div class="code-block-body"><span class="code-block-language" title="Language swift">swift</span><pre class="shiki dash-light" tabindex="0"><code><span class="line"><span style="color:#6E6E70">// iOS (Swift)</span></span> <span class="line"><span style="color:#BD2314">let</span><span style="color:#222222"> channel = </span><span style="color:#6200EE">FlutterMethodChannel</span><span style="color:#222222">(</span><span style="color:#6200EE">name</span><span style="color:#222222">: </span><span style="color:#0C7064">"foo"</span><span style="color:#222222">, </span><span style="color:#6200EE">binaryMessenger</span><span style="color:#222222">: flutterView)</span></span> <span class="line"><span style="color:#222222">channel.</span><span style="color:#6200EE">setMethodCallHandler</span><span style="color:#222222"> {</span></span> <span class="line"><span style="color:#222222"> (</span><span style="color:#6200EE">call</span><span style="color:#222222">: FlutterMethodCall, </span><span style="color:#6200EE">result</span><span style="color:#222222">: FlutterResult) -> </span><span style="color:#0468D7">Void</span><span style="color:#BD2314"> in</span></span> <span class="line"><span style="color:#BD2314"> switch</span><span style="color:#222222"> (call.method) {</span></span> <span class="line"><span style="color:#BD2314"> case</span><span style="color:#0C7064"> "bar"</span><span style="color:#222222">: </span><span style="color:#6200EE">result</span><span style="color:#222222">(</span><span style="color:#0C7064">"Hello, </span><span style="color:#222222">\(</span><span style="color:#0C7064">call.</span><span style="color:#222222">arguments</span><span style="color:#222222"> as!</span><span style="color:#0468D7"> String</span><span style="color:#222222">)</span><span style="color:#0C7064">"</span><span style="color:#222222">)</span></span> <span class="line"><span style="color:#BD2314"> default</span><span style="color:#222222">: </span><span style="color:#6200EE">result</span><span style="color:#222222">(FlutterMethodNotImplemented)</span></span> <span class="line"><span style="color:#222222"> }</span></span> <span class="line"><span style="color:#222222">}</span></span></code></pre></div></div><p>Further examples of using platform channels, including examples for desktop platforms, can be found in the <a href="https://github.com/flutter/packages">flutter/packages</a> repository. There are also <a href="https://pub.dev/flutter">thousands of plugins already available</a> for Flutter that cover many common scenarios, ranging from Firebase to ads to device hardware like camera and Bluetooth.</p><div class="header-wrapper"><h3 id="foreign-function-interface-ffi">Foreign Function Interface (FFI)</h3><a class="heading-link" href="#foreign-function-interface-ffi" aria-label="Link to 'Foreign Function Interface (FFI)' section">#</a></div><p>For C-based APIs, including those that can be generated for code written in modern languages like Rust or Go, Dart provides a direct mechanism for binding to native code using the <code>dart:ffi</code> library. The foreign function interface (FFI) model can be considerably faster than platform channels, because no serialization is required to pass data. Instead, the Dart runtime provides the ability to allocate memory on the heap that is backed by a Dart object and make calls to statically or dynamically linked libraries. FFI is available for all platforms other than web, where the <a href="https://dart.dev/interop/js-interop">JS interop libraries</a> and <a href="https://pub.dev/packages/web"><code>package:web</code></a> serve a similar purpose.</p><p>To use FFI, you create a <code>typedef</code> for each of the Dart and unmanaged method signatures, and instruct the Dart VM to map between them. As an example, here's a fragment of code to call the traditional Win32 <code>MessageBox()</code> API:</p> <?code-excerpt "lib/ffi.dart" remove="ignore:"?> <div class="code-block-wrapper language-dart"><div class="code-block-body"><span class="code-block-language" title="Language dart">dart</span><pre class="shiki dash-light" tabindex="0"><code><span class="line"><span style="color:#BD2314">import</span><span style="color:#0C7064"> 'dart:ffi'</span><span style="color:#222222">;</span></span> <span class="line"><span style="color:#BD2314">import</span><span style="color:#0C7064"> 'package:ffi/ffi.dart'</span><span style="color:#222222">; </span><span style="color:#6E6E70">// contains .toNativeUtf16() extension method</span></span> <span class="line"></span> <span class="line"><span style="color:#BD2314">typedef</span><span style="color:#0468D7"> MessageBoxNative</span><span style="color:#222222"> =</span></span> <span class="line"><span style="color:#0468D7"> Int32</span><span style="color:#0468D7"> Function</span><span style="color:#222222">(</span></span> <span class="line"><span style="color:#0468D7"> IntPtr</span><span style="color:#222222"> hWnd,</span></span> <span class="line"><span style="color:#0468D7"> Pointer</span><span style="color:#222222"><</span><span style="color:#0468D7">Utf16</span><span style="color:#222222">> lpText,</span></span> <span class="line"><span style="color:#0468D7"> Pointer</span><span style="color:#222222"><</span><span style="color:#0468D7">Utf16</span><span style="color:#222222">> lpCaption,</span></span> <span class="line"><span style="color:#0468D7"> Int32</span><span style="color:#222222"> uType,</span></span> <span class="line"><span style="color:#222222"> );</span></span> <span class="line"></span> <span class="line"><span style="color:#BD2314">typedef</span><span style="color:#0468D7"> MessageBoxDart</span><span style="color:#222222"> =</span></span> <span class="line"><span style="color:#0468D7"> int</span><span style="color:#0468D7"> Function</span><span style="color:#222222">(</span></span> <span class="line"><span style="color:#0468D7"> int</span><span style="color:#222222"> hWnd,</span></span> <span class="line"><span style="color:#0468D7"> Pointer</span><span style="color:#222222"><</span><span style="color:#0468D7">Utf16</span><span style="color:#222222">> lpText,</span></span> <span class="line"><span style="color:#0468D7"> Pointer</span><span style="color:#222222"><</span><span style="color:#0468D7">Utf16</span><span style="color:#222222">> lpCaption,</span></span> <span class="line"><span style="color:#0468D7"> int</span><span style="color:#222222"> uType,</span></span> <span class="line"><span style="color:#222222"> );</span></span> <span class="line"></span> <span class="line"><span style="color:#BD2314">void</span><span style="color:#6200EE"> exampleFfi</span><span style="color:#222222">() {</span></span> <span class="line"><span style="color:#BD2314"> final</span><span style="color:#222222"> user32 = </span><span style="color:#0468D7">DynamicLibrary</span><span style="color:#222222">.</span><span style="color:#6200EE">open</span><span style="color:#222222">(</span><span style="color:#0C7064">'user32.dll'</span><span style="color:#222222">);</span></span> <span class="line"><span style="color:#BD2314"> final</span><span style="color:#222222"> messageBox = user32.</span><span style="color:#6200EE">lookupFunction</span><span style="color:#222222"><</span><span style="color:#0468D7">MessageBoxNative</span><span style="color:#222222">, </span><span style="color:#0468D7">MessageBoxDart</span><span style="color:#222222">>(</span></span> <span class="line"><span style="color:#0C7064"> 'MessageBoxW'</span><span style="color:#222222">,</span></span> <span class="line"><span style="color:#222222"> );</span></span> <span class="line"></span> <span class="line"><span style="color:#BD2314"> final</span><span style="color:#222222"> result = </span><span style="color:#6200EE">messageBox</span><span style="color:#222222">(</span></span> <span class="line"><span style="color:#0C7064"> 0</span><span style="color:#222222">, </span><span style="color:#6E6E70">// No owner window</span></span> <span class="line"><span style="color:#0C7064"> 'Test message'</span><span style="color:#222222">.</span><span style="color:#6200EE">toNativeUtf16</span><span style="color:#222222">(), </span><span style="color:#6E6E70">// Message</span></span> <span class="line"><span style="color:#0C7064"> 'Window caption'</span><span style="color:#222222">.</span><span style="color:#6200EE">toNativeUtf16</span><span style="color:#222222">(), </span><span style="color:#6E6E70">// Window title</span></span> <span class="line"><span style="color:#0C7064"> 0</span><span style="color:#222222">, </span><span style="color:#6E6E70">// OK button only</span></span> <span class="line"><span style="color:#222222"> );</span></span> <span class="line"><span style="color:#222222">}</span></span></code></pre></div></div><div class="header-wrapper"><h3 id="rendering-native-controls-in-a-flutter-app">Rendering native controls in a Flutter app</h3><a class="heading-link" href="#rendering-native-controls-in-a-flutter-app" aria-label="Link to 'Rendering native controls in a Flutter app' section">#</a></div><p>Because Flutter content is drawn to a texture and its widget tree is entirely internal, there's no place for something like an Android view to exist within Flutter's internal model or render interleaved within Flutter widgets. That's a problem for developers that would like to include existing platform components in their Flutter apps, such as a browser control.</p><p>Flutter solves this by introducing platform view widgets (<a href="https://api.flutter.dev/flutter/widgets/AndroidView-class.html"><code>AndroidView</code></a> and <a href="https://api.flutter.dev/flutter/widgets/UiKitView-class.html"><code>UiKitView</code></a>) that let you embed this kind of content on each platform. Platform views can be integrated with other Flutter content<sup class="footnote-ref"><a href="#fn3" id="fnref3">[3]</a></sup>. Each of these widgets acts as an intermediary to the underlying operating system. For example, on Android, <code>AndroidView</code> serves three primary functions:</p><ul><li>Making a copy of the graphics texture rendered by the native view and presenting it to Flutter for composition as part of a Flutter-rendered surface each time the frame is painted.</li><li>Responding to hit testing and input gestures, and translating those into the equivalent native input.</li><li>Creating an analog of the accessibility tree, and passing commands and responses between the native and Flutter layers.</li></ul><p>Inevitably, there is a certain amount of overhead associated with this synchronization. In general, therefore, this approach is best suited for complex controls like Google Maps where reimplementing in Flutter isn't practical.</p><p>Typically, a Flutter app instantiates these widgets in a <code>build()</code> method based on a platform test. As an example, from the <a href="https://pub.dev/packages/google_maps_flutter">google_maps_flutter</a> plugin:</p><div class="code-block-wrapper language-dart"><div class="code-block-body"><span class="code-block-language" title="Language dart">dart</span><pre class="shiki dash-light" tabindex="0"><code><span class="line"><span style="color:#BD2314">if</span><span style="color:#222222"> (defaultTargetPlatform == </span><span style="color:#0468D7">TargetPlatform</span><span style="color:#222222">.android) {</span></span> <span class="line"><span style="color:#BD2314"> return</span><span style="color:#0468D7"> AndroidView</span><span style="color:#222222">(</span></span> <span class="line"><span style="color:#222222"> viewType: </span><span style="color:#0C7064">'plugins.flutter.io/google_maps'</span><span style="color:#222222">,</span></span> <span class="line"><span style="color:#222222"> onPlatformViewCreated: onPlatformViewCreated,</span></span> <span class="line"><span style="color:#222222"> gestureRecognizers: gestureRecognizers,</span></span> <span class="line"><span style="color:#222222"> creationParams: creationParams,</span></span> <span class="line"><span style="color:#222222"> creationParamsCodec: </span><span style="color:#BD2314">const</span><span style="color:#0468D7"> StandardMessageCodec</span><span style="color:#222222">(),</span></span> <span class="line"><span style="color:#222222"> );</span></span> <span class="line"><span style="color:#222222">} </span><span style="color:#BD2314">else</span><span style="color:#BD2314"> if</span><span style="color:#222222"> (defaultTargetPlatform == </span><span style="color:#0468D7">TargetPlatform</span><span style="color:#222222">.iOS) {</span></span> <span class="line"><span style="color:#BD2314"> return</span><span style="color:#0468D7"> UiKitView</span><span style="color:#222222">(</span></span> <span class="line"><span style="color:#222222"> viewType: </span><span style="color:#0C7064">'plugins.flutter.io/google_maps'</span><span style="color:#222222">,</span></span> <span class="line"><span style="color:#222222"> onPlatformViewCreated: onPlatformViewCreated,</span></span> <span class="line"><span style="color:#222222"> gestureRecognizers: gestureRecognizers,</span></span> <span class="line"><span style="color:#222222"> creationParams: creationParams,</span></span> <span class="line"><span style="color:#222222"> creationParamsCodec: </span><span style="color:#BD2314">const</span><span style="color:#0468D7"> StandardMessageCodec</span><span style="color:#222222">(),</span></span> <span class="line"><span style="color:#222222"> );</span></span> <span class="line"><span style="color:#222222">}</span></span> <span class="line"><span style="color:#BD2314">return</span><span style="color:#0468D7"> Text</span><span style="color:#222222">(</span></span> <span class="line"><span style="color:#0C7064"> '</span><span style="color:#0C7064">$</span><span style="color:#222222">defaultTargetPlatform</span><span style="color:#0C7064"> is not yet supported by the maps plugin'</span><span style="color:#222222">);</span></span></code></pre></div></div><p>Communicating with the native code underlying the <code>AndroidView</code> or <code>UiKitView</code> typically occurs using the platform channels mechanism, as previously described.</p><p>At present, platform views aren't available for desktop platforms, but this is not an architectural limitation; support might be added in the future.</p><div class="header-wrapper"><h3 id="hosting-flutter-content-in-a-parent-app">Hosting Flutter content in a parent app</h3><a class="heading-link" href="#hosting-flutter-content-in-a-parent-app" aria-label="Link to 'Hosting Flutter content in a parent app' section">#</a></div><p>The converse of the preceding scenario is embedding a Flutter widget in an existing Android or iOS app. As described in an earlier section, a newly created Flutter app running on a mobile device is hosted in an Android activity or iOS <code>UIViewController</code>. Flutter content can be embedded into an existing Android or iOS app using the same embedding API.</p><p>The Flutter module template is designed for easy embedding; you can either embed it as a source dependency into an existing Gradle or Xcode build definition, or you can compile it into an Android Archive or iOS Framework binary for use without requiring every developer to have Flutter installed.</p><p>The Flutter engine takes a short while to initialize, because it needs to load Flutter shared libraries, initialize the Dart runtime, create and run a Dart isolate, and attach a rendering surface to the UI. To minimize any UI delays when presenting Flutter content, it's best to initialize the Flutter engine during the overall app initialization sequence, or at least ahead of the first Flutter screen, so that users don't experience a sudden pause while the first Flutter code is loaded. In addition, separating the Flutter engine allows it to be reused across multiple Flutter screens and share the memory overhead involved with loading the necessary libraries.</p><p>More information about how Flutter is loaded into an existing Android or iOS app can be found at the <a href="/add-to-app/performance">Load sequence, performance and memory topic</a>.</p><div class="header-wrapper"><h2 id="flutter-web-support">Flutter web support</h2><a class="heading-link" href="#flutter-web-support" aria-label="Link to 'Flutter web support' section">#</a></div><p>While the general architectural concepts apply to all platforms that Flutter supports, there are some unique characteristics of Flutter's web support that are worthy of comment.</p><p>Dart has been compiling to JavaScript for as long as the language has existed, with a toolchain optimized for both development and production purposes. Many important apps compile from Dart to JavaScript and run in production today, including the <a href="https://ads.google.com/home/">advertiser tooling for Google Ads</a>. Because the Flutter framework is written in Dart, compiling it to JavaScript was relatively straightforward.</p><p>However, the Flutter engine, written in C++, is designed to interface with the underlying operating system rather than a web browser. A different approach is therefore required.</p><p>On the web, Flutter offers two renderers:</p><table class="table table-striped"><tr><th>Renderer</th><th>Compilation target</th></tr><tr><td>CanvasKit</td><td>JavaScript</td></tr><tr><td>Skwasm</td><td>WebAssembly</td></tr></table><p><em>Build modes</em> are command-line options that dictate which renderers are available when you run the app.</p><p>Flutter offers two <em>build</em> modes:</p><table class="table table-striped"><tr><th>Build mode</th><th>Available renderer(s)</th></tr><tr><td>default</td><td>CanvasKit</td></tr><tr><td>`--wasm`</td><td>Skwasm (preferred), CanvasKit (fallback)</td></tr><p>The default mode makes only CanvasKit renderer available. The <code>--wasm</code> option makes both renderers available, and chooses the engine based on browser capabilities: preferring Skwasm if the browser is capable of running it, and falls back to CanvasKit otherwise.</p><p><img src="/assets/images/docs/arch-overview/web-framework-diagram.drawio.png" alt="Flutter web architecture" width="100%"></p><p>Perhaps the most notable difference compared to other platforms on which Flutter runs is that there is no need for Flutter to provide a Dart runtime. Instead, the Flutter framework (along with any code you write) is compiled to JavaScript. It's also worthy to note that Dart has very few language semantic differences across all of its modes (JIT versus AOT, native versus web compilation), and most developers will never write a line of code that runs into such a difference.</p><p>During development time, Flutter web uses <a href="https://dart.dev/tools/dartdevc"><code>dartdevc</code></a>, a compiler that supports incremental compilation and therefore allows hot restart (although not currently hot reload) for apps. Conversely, when you are ready to create a production app for the web, <a href="https://dart.dev/tools/dart2js"><code>dart2js</code></a>, Dart's highly-optimized production JavaScript compiler is used, packaging the Flutter core and framework along with your application into a minified source file that can be deployed to any web server. Code can be offered in a single file or split into multiple files through <a href="https://dart.dev/language/libraries#lazily-loading-a-library">deferred imports</a>.</p><p>For more information on Flutter web, check out <a href="/platform-integration/web">Web support for Flutter</a> and <a href="/platform-integration/web/renderers">Web renderers</a>.</p><div class="header-wrapper"><h2 id="further-information">Further information</h2><a class="heading-link" href="#further-information" aria-label="Link to 'Further information' section">#</a></div><p>For those interested in more information about the internals of Flutter, the <a href="/resources/inside-flutter">Inside Flutter</a> whitepaper provides a useful guide to the framework's design philosophy.</p><hr class="footnotes-sep"><section class="footnotes"><ol class="footnotes-list"><li id="fn1" class="footnote-item"><p>While the <code>build</code> function returns a fresh tree, you only need to return something <em>different</em> if there's some new configuration to incorporate. If the configuration is in fact the same, you can just return the same widget. <a href="#fnref1" class="footnote-backref">鈫╋笌</a></p></li><li id="fn2" class="footnote-item"><p>This is a slight simplification for ease of reading. In practice, the tree might be more complex. <a href="#fnref2" class="footnote-backref">鈫╋笌</a></p></li><li id="fn3" class="footnote-item"><p>There are some limitations with this approach, for example, transparency doesn't composite the same way for a platform view as it would for other Flutter widgets. <a href="#fnref3" class="footnote-backref">鈫╋笌</a></p></li></ol></section><p id="page-github-links"><span>Unless stated otherwise, the documentation on this site reflects the latest stable version of Flutter. Page last updated on 2025-02-12.</span> <a href="https://github.com/flutter/website/tree/main/src/content/resources/architectural-overview.md" target="_blank" rel="noopener">View source</a> <span>or </span><a href="https://github.com/flutter/website/issues/new?template=1_page_issue.yml&&page-url=https://docs.flutter.dev/resources/architectural-overview/&page-source=https://github.com/flutter/website/tree/main/src/content/resources/architectural-overview.md" title="Report an issue with this page" target="_blank" rel="noopener">report an issue</a>.</p></table></article></main></div><footer id="site-footer"><div class="footer-section footer-main"><a class="brand" href="https://flutter.dev"><img src="/assets/images/branding/flutter/logo+text/horizontal/white.svg" alt="Flutter logo" width="164"></a><div class="footer-social-links"><a class="icon-button" href="https://medium.com/flutter" target="_blank" rel="noopener" title="Flutter's Medium blog"><svg><use href="/assets/images/social/medium.svg#medium"></use></svg> </a><a class="icon-button" href="https://youtube.com/@flutterdev" target="_blank" rel="noopener" title="Flutter's YouTube"><svg><use href="/assets/images/social/youtube.svg#youtube"></use></svg> </a><a class="icon-button" href="https://github.com/flutter" target="_blank" rel="noopener" title="Flutter's GitHub"><svg><use href="/assets/images/social/github.svg#github"></use></svg> </a><a class="icon-button" href="https://bsky.app/profile/flutter.dev" target="_blank" rel="noopener" title="Flutter's Bluesky"><svg><use href="/assets/images/social/bluesky.svg#bluesky"></use></svg> </a><a class="icon-button" href="https://twitter.com/FlutterDev" target="_blank" rel="noopener" title="Flutter's X (Twitter)"><svg><use href="/assets/images/social/x.svg#x"></use></svg></a></div></div><div class="footer-section footer-tray"><div class="footer-licenses">Except as otherwise noted, this site is licensed under a <a href="https://creativecommons.org/licenses/by/4.0/">Creative Commons Attribution 4.0 International License</a>, and code samples are licensed under the <a href="https://opensource.org/licenses/BSD-3-Clause">3-Clause BSD License</a>.</div><div class="footer-utility-links"><ul><li><a href="/tos" title="Terms of use">Terms</a></li><li><a href="/brand" title="Brand usage guidelines">Brand</a></li><li><a href="https://policies.google.com/privacy" target="_blank" rel="noopener" title="Privacy policy">Privacy</a></li><li><a href="/security" title="Security philosophy and practices">Security</a></li></ul></div></div></footer></div><script src="/assets/js/tabs.js?v=4"></script><script src="/assets/js/archive.js?v=4"></script><script src="/assets/js/main.js?v=4"></script></body></html>