Widgets, state and native code in a Flutter build
Why Flutter draws its own pixels
Flutter does not wrap the buttons and lists that iOS and Android provide. It ships a rendering engine inside your app and paints every widget itself, from Dart code compiled ahead of time to native machine code. The benefit is consistency: a screen looks and behaves the same on a new iPhone and on an Android phone that is several years old, and your designer gets exactly the layout they drew. The cost is that platform look and feel becomes your responsibility. We build adaptive widgets for navigation bars, pickers, switches and scroll physics so the app does not feel like a port.
Choosing between Provider, Riverpod and Bloc
All three work. Provider is simple and fine for small apps with a handful of shared objects. Riverpod removes the dependence on the widget tree, catches more mistakes at compile time and is our usual choice for new projects. Bloc asks for more code per feature, with explicit events and states, and repays it in large apps where several developers need the same strict pattern and a clear trail of what happened. What matters more than the library is using one approach everywhere and keeping business logic out of widgets. Mixed patterns are the most common thing we clean up in Flutter apps we inherit.
When Dart is not enough
Camera, location, biometrics, payments and push notifications have maintained packages. For anything else, such as a card reader SDK, a proprietary Bluetooth device or a bank's native library, we write Kotlin and Swift and expose it to Dart through platform channels, with typed interfaces generated so the two sides cannot drift apart. Before adding any third-party package we check who maintains it and how it handles the current OS permission model, because an abandoned plugin is the usual reason a Flutter app cannot be upgraded.
Keeping it fast
Flutter is quick by default and easy to slow down. We build long lists lazily, mark widgets const where we can, keep rebuilds narrow, resize and cache images, and move JSON parsing or other heavy work to a background isolate. Then we profile on a cheap Android phone in profile mode, not on the simulator, since that is where dropped frames show up.
When we would not use Flutter
If the product is mostly an OS feature (a home screen widget, a watch app, a keyboard, an in-car experience), native code does the main job and Flutter adds weight. The same goes for very small utility apps where download size matters, and for teams with strong native developers already in place. In those cases we point you to native iOS or Android development.