Mobile Development

Flutter app development for iOS and Android

Flutter lets one team build iOS and Android apps from a single Dart codebase, with its own engine drawing every screen. It suits products that need a consistent, custom interface on both platforms. It is a weaker fit when an app leans on platform-specific features or must match each operating system's native look exactly. This page explains how we judge that.

Start a project

When Flutter is a good fit, and when it is not

Flutter is a user interface toolkit from Google. You write the app once in Dart and build it for iOS and Android. A cross-platform app like this means one team, one backlog and one set of business logic.

It fits well when:

  • Your design is custom and brand-led, and should look the same on both platforms.
  • A small team must ship iOS and Android together and keep their features in step.
  • The app is mostly screens, forms, lists, maps and payments backed by an API.

It fits less well when:

  • The app needs deep device features such as a custom camera pipeline, augmented reality, background Bluetooth, watch apps or widgets. These need native code, and the more you need, the less Flutter saves. See native iOS and Android development.
  • You want new system styling the day an operating system ships. Flutter draws its own widgets, so it arrives later.
  • Download size is critical. A Flutter app carries its engine.
  • Your team works in TypeScript and React, which points to React Native. Our comparison, Flutter vs React Native, sets the two side by side.

How Flutter renders your app

Many frameworks wrap the platform's own buttons and lists. Flutter draws every pixel itself with its own rendering engine. Your screen is a tree of widgets, small composable pieces such as text, padding and buttons, and when state changes Flutter rebuilds only the affected ones.

Layout and animation therefore behave the same on iOS and Android. But the interface is not built from native controls, so text selection, scroll feel and screen reader behaviour are Flutter's own and need checking on real devices. Release builds compile Dart ahead of time to native code, so always profile a release or profile build, never a debug build.

Performance: what to watch

A Flutter app can run smoothly at the screen's refresh rate, but you have to protect that. The problems we look for early:

  • Long lists built all at once. Use lazy builders so only visible rows exist.
  • Heavy work on the main thread. Parse large responses and process images in a separate isolate, Dart's way of running work in parallel.
  • Widgets that rebuild too much. Keep state close to where it is used.
  • Oversized images. Decode them at display size and cache them.

Measure with Flutter DevTools on a real mid-range phone, not a simulator. Set a small performance budget at the start and check it at each weekly demo.

Plugins and native code

Most device features reach Flutter through plugins from the pub.dev registry: camera, location, notifications, secure storage. When none exists, you write a little Swift and Kotlin and call it from Dart through a platform channel, or embed a native view such as a map.

Each plugin is a dependency on someone else's upkeep, and it is where Flutter projects most often get into trouble. Before adding one we check when it was last released, whether it supports both platforms, who publishes it, which permissions it adds and how hard it would be to replace.

State management and architecture

Flutter does not force one way to organise an app, so the team must choose a pattern and apply it everywhere. Popular state tools include Provider, Riverpod and Bloc, and any of them works if every feature follows it.

The principles matter more than the library. Keep the interface, the state and logic, and the data layer (API, storage, device services) apart. Put outside services behind interfaces so tests can fake them, and organise code by feature. That structure is what lets an app grow past its first version without becoming a tangle.

Testing a Flutter app

Flutter supports several levels of automated test, and they work best together:

  • Unit tests for business rules and state logic.
  • Widget tests that build a screen and check what it shows and how it reacts.
  • Golden tests that compare a screen with a saved image, including in Arabic and at large text sizes.
  • Integration tests that drive the real app through sign-in or checkout.

Automated tests do not replace devices. Before each release, run the main flows on a few physical iOS and Android phones, including an older Android model.

Releasing to the App Store and Google Play

A Flutter app ships as an iOS archive, built with Xcode on a Mac, and an Android App Bundle for Google Play. The setup is easier at the start of a project than in launch week:

  • Separate staging and production environments with their own keys.
  • Signing: Apple certificates and provisioning profiles, and an Android upload key.
  • A pipeline that builds, tests and signs every change.
  • Beta distribution through TestFlight and the Google Play testing tracks.
  • Store listings and privacy declarations in each language you support.

Review times and rules differ between the stores and change over time, so leave a buffer around any fixed launch date.

Right-to-left and Arabic in Flutter

Flutter follows the text direction of the current locale, as long as the layout uses start and end instead of left and right, for example directional padding and alignment. The same screen then works in English and Arabic. Right-to-left still needs deliberate work:

  • Mirror directional icons such as arrows, but not logos or media controls.
  • Keep strings in translation files, and plan for text that is longer or shorter.
  • Format dates, numbers and currencies by locale.
  • Test mixed Arabic and Latin text, and check the Arabic font's line height.

We design and review each screen in both directions from the start. For the design side, see Arabic and RTL design.

Mobile security for Flutter apps

Assume that anything inside an app can be read. Every project starts with a threat review, and a security review before launch gives a prioritised fix list. For Flutter, the usual measures are:

  • Secure storage. Keep tokens and keys in the iOS Keychain and the Android Keystore, through a secure-storage plugin, never in plain preferences.
  • Certificate pinning. Pin your API's public key, include a backup and plan for rotation, or a routine certificate change can lock users out.
  • Code obfuscation. Flutter can obfuscate Dart symbols in release builds. Keep the symbol files so crash reports stay readable. It slows reverse engineering; it does not stop it.
  • Rooted and jailbroken devices. Detection can be bypassed, so treat it as one signal: warn, limit sensitive features and check on the server.
  • No secrets in the binary. Keep real keys on the server.

The OWASP Mobile Application Security Verification Standard (MASVS) makes a good checklist. Our cybersecurity service includes testing a mobile app before release, and the guide to secure app development goes deeper.

Rule of thumb: choose Flutter for the product, not for the plugin list. If your three most important features each need custom native code, compare the cost with native development before you commit.

Questions we get asked

  • Yes, when the product fits it. Flutter compiles to native code for release and has mature tooling and a large plugin ecosystem. The architecture, the plugin choices and testing on real devices decide the outcome more than the framework does. We judge fit during a discovery sprint.

  • Yes. Most features come through plugins. For anything a plugin does not cover, we write Swift or Kotlin and call it from Dart through a platform channel. If a large share of the app needs this, native development may be the better route.

  • Yes. Flutter follows the locale's text direction and supports localisation, provided the layout uses start and end instead of left and right. You still need to mirror directional icons and test mixed Arabic and Latin text. We build and review both languages from the first screen.

  • It can be, with the right design. Store secrets in the Keychain and Keystore, pin certificates, keep real secrets on the server and review the app before release. No framework makes an app secure on its own. A threat review at the start decides which measures a given app needs.

Keep exploring

Ready to build something secure?

Tell us about your product. We will reply with a clear plan.

Start a project

We would like to use Microsoft Clarity to see how visitors use the site, so we can improve it. It sets cookies and is off unless you accept. Cookie policy