Flutter Trending
Flutter 趋势
汇总 GitHub、Dev.to、freeCodeCamp、Hacker News、Medium、Reddit 的近期热门内容。
GitHub
20 条Dart 与 Flutter 相关仓库热度
chen08209/FlClash
更新于 07/22 06:32
localsend/localsend
更新于 07/22 06:32
spotiflacapp/SpotiFLAC-Mobile
更新于 07/22 06:09
Predidit/Kazumi
更新于 07/22 06:00
AppFlowy-IO/AppFlowy
更新于 07/22 06:25
flutter/flutter
更新于 07/22 06:46
bggRGjQaUbCoE/PiliPlus
更新于 07/22 01:32
KaringX/karing
更新于 07/22 02:48
KRTirtho/spotube
更新于 07/22 05:39
echo-loop/Echo-Loop
更新于 07/21 23:05
hiddify/hiddify-app
更新于 07/22 06:11
ente/ente
更新于 07/22 06:45
bagisto/opensource-ecommerce-mobile-app
更新于 07/22 03:36
KaringX/clashmi
更新于 07/22 06:06
ImranR98/Obtainium
更新于 07/22 03:29
Sle2p/AniCh
更新于 07/22 01:45
Chevey339/kelivo
更新于 07/22 01:42
simonoppowa/OpenNutriTracker
更新于 07/22 04:36
venera-app/venera
更新于 07/22 03:02
jiangtian616/JHenTai
更新于 07/21 22:10
Dev.to
12 条开发者文章与项目分享
Delivering messages with no internet, no servers, and no SIM
Royal Simpson Pinto
Every messenger you use has a hidden dependency: a working network path to a datacenter. Drop into a basement, a packed stadium, a moving train through a tunnel, an exam hall with jammers, or a remote area with no plan, and the app is just a spinner. The people you want to reach are often standing a few meters away, but your message still has to travel to a server on another continent and back. When that path is gone, so is the app. Kabootar is my attempt to remove that dependency entirely. It is a messenger with no backend at all. Your phone forms a peer-to-peer mesh with other phones nearby, and messages hop device to device over Bluetooth and Wi-Fi until they reach the recipient. No internet, no servers, no SIM. It is built in Flutter, and the routing core is plain Dart. The insight that makes this work is refusing to assume the recipient is reachable right now. Normal networking is connection-oriented: open a path end to end, then send. If there is no path, there is no delivery. Kabootar instead treats the network as a delay-tolerant network (DTN). A message does not need a live end-to-end path at the moment you hit send. It needs a chain of carriers that will exist over time. You hand your message to whoever is nearby. They hold onto it, carry it as they walk around, and pass it along to the next phone they meet. Eventually a carrier bumps into the recipient and the message lands, even if that is minutes later and both you and the recipient have long since walked away. This is store-and-forward, the same shape as a durable, at-least-once message queue, except the queue is running across a swarm of phones instead of inside a datacenter. The routing strategy is epidemic routing: flooding. When you send a message, it spreads to everyone in range like a rumor. Each device that receives it re-broadcasts it onward, so the message replicates through the crowd, taking every path at once. That redundancy is exactly what makes delivery robust in a network where any single link is unreliable and short-lived. The whole routing brain lives in one place: a framework-free Dart MeshEngine with zero Flutter, radio, or database imports. Every phone applies the same small set of rules to each envelope it sees: De-dup by message id. A message can arrive by many paths, but it is acted on exactly once. This is what stops flood storms and routing loops. Learn from a hello. The contact list is built from whoever comes near, via a handshake. Deliver if it is for me. Save it, show it, and send back an ack. Receipt on an ack. When the acknowledgement for one of my sent messages makes it back to me, I flip that message to delivered. Relay and carry otherwise. Decrement the time-to-live, cache it, and re-flood it onward. Cap everything. TTL, a max-age, and a cache-size bound keep battery and storage in check so a carrier stays honest. That is the entire mesh in six rules. Delivery receipts are genuinely end to end: the ack epidemically routes back to the original sender the same way the message went out, so the WhatsApp-style double tick means the message really reached the recipient's device, not just some server. Because de-dup uses the message id and that seen-set is persisted to SQLite, the system survives restarts. A phone that reboots mid-mesh will not re-flood messages it has already handled. At-least-once delivery becomes effectively exactly-once at the edges. Under the engine sits a MeshTransport interface, implemented on top of the platform peer-to-peer stacks (Nearby Connections on Android, Multipeer-style discovery on iOS) through flutter_nearby_connections. Phones continuously advertise and scan, form short-lived peer links over Bluetooth and Wi-Fi, and flush their carried messages whenever a link comes up. The architecture keeps a clean seam. The UI is Material 3 and binds to a single ChatService, which owns state, the hello handshake, and receipt ticks. ChatService talks to the pure MeshEngine for routing decisions, to SQLite for persistence, and to the transport for the actual radios. Because the engine has no framework or hardware dependencies, its behavior is pinned down by tests that run on a laptop with just the Dart SDK. You can watch store-and-forward-across-time play out (recipient offline, a relay carrying, delivery after the recipient returns, sender eventually learning it was delivered) without touching a phone by running dart run tool/engine_check.dart. Direct chats and private groups are end-to-end encrypted with X25519, Ed25519, and AES-GCM, with signed messages and a safety code to verify a contact. Relays only ever see ciphertext, which matters a lot when your "relay" is a stranger's phone in a crowd. Mesh delivery is only as good as the crowd. Delivery needs a chain of carriers to physically exist between you and the recipient over some window of time. In a dense place, a festival, a protest, a stadium, that chain forms readily and messages move fast. In a sparse setting with few phones running the
Flutter Assumes There Is Only One Window. I Gave It Two.
K M Shahriar Hossain
Document Picture-in-Picture is a browser API that gives you a real operating Chrome and Edge have had it since 116. Firefox shipped it in 151. Almost document_pip to find out why. The API itself is about four lines. The difficulty is entirely on the Flutter the engine is built on the assumption that there Not stated anywhere as a constraint — just quietly baked into The first wall is structural. Multi-view Flutter has no single root, so an app runWidget, not runApp. That part is The part that is not: only the JavaScript app object returned by engine.runApp() can add a view. dart:ui_web exposes the view list const engine = await engineInitializer.initializeEngine({ multiViewEnabled: true, }); const app = await engine.runApp(); window.documentPipApp = app; // the package needs this app.addView({ hostElement: document.querySelector('#app') }); Multi-view is a property of how the engine starts. Nothing published to One trap in that snippet. Never pass document.body as hostElement. Flutter body Here is the good one. You open the pop-out, switch to another tab to do the thing you opened it for, The cause is a disagreement between two true statements. Chromium keeps still reports the page as hidden, because by any normal definition it is: Flutter's web engine reads visibilityState: "hidden" and turns it into AppLifecycleState.hidden. SchedulerBinding responds by clearing framesEnabled, after which scheduleFrame() returns early forever. That is can still see is the one Flutter just stopped drawing. Measured rather than argued, because the whole failure is about believing a Chromium, tab in the background browser frames Flutter frames no pop-out open 2 in 2.5s — pop-out open 302 in 2.5s 0 in 3s pop-out open, with the fix 302 in 2.5s 311 in 3s The browser was drawing at roughly 120fps. Flutter drew nothing. scheduleForcedFrame() is the documented way past it — it ignores framesEnabled and only checks whether a frame is already pending. So the root void _keepPaintingWhileHidden(Duration _) { if (!mounted) return; final binding = WidgetsBinding.instance; if (binding.framesEnabled) return; // page is back if (DocumentPip.popOutViewIds.isEmpty) return; // last window closed binding.scheduleForcedFrame(); binding.addPostFrameCallback(_keepPaintingWhileHidden); } Both guards end the loop on their own, which matters: this is a hand-rolled State And it is a Chromium problem specifically. Firefox 151 and 155 keep reporting visible with a pop-out open — 308 frames in 2.5s against 9 for the framesEnabled is never cleared and that first The second singleton. Flutter's KeyboardBinding attaches capture-phase keydown/keyup listeners once, globally, to the opener's window. A window, What makes this genuinely nasty is which half breaks. Type into a text field in Everything that travels as a key event is dead: Shortcuts, Actions, Focus.onKeyEvent, HardwareKeyboard, Escape, Tab traversal. Text selection selectionchange document — so moving the caret with the The fix is to replay the events into the opener and hand Flutter's focus to the // One tear-off each, kept: every `.toJS` makes a NEW JS function, so // removing with a second one silently leaves the listener attached. late final JSFunction _onKeyRef = _onKey.toJS; .toJS on the same Dart function twice gives you two different JavaScript removeEventListener compares by identity, finds nothing, removes addEventListener you write in Dart, and it fails as a leak Keys held when a window closes are released explicitly, too. Otherwise HardwareKeyboard still believes they are down, and the next real press of the open() must be the first await in a gesture handler. The browser only after: onPressed: () async { final window = await DocumentPip.open(); // first final data = await fetchTrack(); // then } Get it wrong and Chrome says NotAllowedError — which it also says when you One window, browser-wide. Not per tab, per browser. Opening a second closes closed completes for that None of these are bugs in Flutter, and I want to be precise about that. Turning They are all the same shape of problem: a framework generalisation that holds The only thing that actually worked was refusing to reason about it. Every document_pip is MIT and on pub.dev; the source is at github.com/devShakib015/flutter_packages. Originally published at devshakib.jumyn.com. I write about Flutter, Dart and the parts of shipping that are genuinely awkward — and publish the packages that came out of them at pub.dev/publishers/jumyn.com.
The Unbreakable Shopping Cart: Pairing BlocSignal with Fast Immutable Collections (FIC) for Bulletproof Flutter Apps
Randal L. Schwartz
The Most Dangerous Line of Code in Flutter Every Flutter developer has stared at this bug in disbelief: A user taps "Add to Cart". The button ripple animates. Your logger prints the updated item. The network request returns HTTP 200. And yet... the screen completely refuses to update. The badge stays at 0, the total stays $0.00, and the UI sits there, completely frozen—until you accidentally tap an unrelated text field or switch tabs, and the items suddenly flash into existence. Or even worse: you build a slick "Undo" button for swiped items. You tap "Undo", and to your horror, your time-travel history stack is completely corrupted. Past state snapshots in memory secretly changed because they were pointing to the exact same mutable list as the present! In Flutter state management, the single most dangerous line of code you can write is not an unhandled Future or a rogue null pointer. It is this: state.items.add(newItem); // 💀 The ghost rebuild trap! Standard Dart collections (List, Set, and Map) are silent ticking time bombs inside reactive architectures. They compare by memory pointer rather than contents, they can be mutated in-place by any layer of your app, and the moment you try to protect yourself with defensive spread copies ([...state.items, newItem]), you pay a brutal tax: allocating and copying thousands of array references on every keystroke, choking the garbage collector, and dropping 120 FPS frames. What if you could have it all? True value equality ([1, 2] == [1, 2] evaluating to true out of the box). Guaranteed compile-time immutability (where in-place mutation bugs cannot even compile). O(1) and O(log N) copy-on-write speed via persistent structural sharing (zero garbage collection churn). 0ms synchronous state de-duplication (dropping duplicate emissions in the exact same frame before a single pixel repaints). And 100% boilerplate-free state classes—without running build_runner for freezed, without writing 30 lines of Equatable props boilerplate, and defined in a single line of Dart 3 record syntax. By pairing BlocSignal with Marcelo Glasberg's acclaimed fast_immutable_collections (FIC), we can build an Unbreakable Shopping Cart and eliminate an entire category of client-side bugs forever. Let us pull back the curtain on the crime scene, dissect the Four Horsemen of collection state bugs, and see how clean reactive architecture is supposed to look. In reactive UI architecture, state management frameworks live or die by state de-duplication. When a state container receives a new emission, it must answer one fundamental question before touching a single pixel or notifying a single subscriber: Has the state actually changed? In BlocSignal, state transitions propagate synchronously in the exact same frame. The moment you call emit(newState) inside a CubitSignal or BlocSignal, the container performs an immediate equality check: if (stateValue == newState) return; If stateValue == newState evaluates to true, BlocSignal immediately drops the transition. It skips creating a Change object, skips executing onChange and onTransition lifecycle hooks, avoids notifying reactive effect() and computed() signals, and completely prevents downstream Flutter widgets from scheduling redundant build passes. This synchronous de-duplication is the secret to 120 FPS performance in BlocSignal. However, when developers model domain state using standard Dart collections (List, Set, and Map), this entire de-duplication mechanism collides with a hidden architectural trap: standard Dart collections do not implement value equality, and they are mutable by default. final listA = ['apple', 'banana']; final listB = ['apple', 'banana']; print(listA == listB); // FALSE! Standard List checks identity (identical memory address). Because standard Dart collections compare memory references (identical) rather than their underlying contents, relying on them inside reactive state containers inevitably unleashes what we call The Four Horsemen of Collection State Bugs: ┌────────────────────────────────────────────────────────────────────────┐ │ THE FOUR HORSEMEN OF COLLECTION STATE BUGS │ ├──────────────────────────┬─────────────────────────────────────────────┤ │ 1. The Ghost Rebuild │ In-place mutation (state.items.add(x)) has │ │ (Skipped Rebuild) │ identical identity: emit() drops the change │ │ │ and Flutter's UI stays frozen! │ ├──────────────────────────┼─────────────────────────────────────────────┤ │ 2. Corrupted Undo Stack │ Time-travel history buffers hold pointers │ │ (Historical Amnesia) │ to the same mutable list: mutating present │ │ │ silently corrupts past snapshots! │ ├──────────────────────────┼─────────────────────────────────────────────┤ │ 3. Defensive Copy Tax │ Writing [...state.items, x] copies N items │ │ (Garbage Collector) │ on every keystroke: memory spikes and 120Hz │ │
Offline-First Flutter Architecture
ROCI
Deep dive into offline caching with Hive and SQLite.
What It Actually Takes to Run a Cross-Border Marketplace: Six Years of Shpper
K M Shahriar Hossain
Shpper is a cross-border personal-shopping marketplace. A buyer wants something I am the CTO. I own the platform end to end — the Flutter apps for both sides, Fourteen major versions is enough distance to say something useful about what The first structural fact about a two-sided marketplace is that "the app" is two The buyer wants their item cheaply, quickly, and with certainty it will arrive. This has a consequence people underestimate: your release cadence is bounded by A change to how offers work is not shipped when the buyer app A marketplace's actual product is trust between strangers. Everything else is Consider what the platform is asking. A buyer sends money for an item that does Neither side would do that for a stranger. They do it because the platform Escrow is not a payments feature, it is the entire trust mechanism. Money is Identity verification is what makes escrow meaningful. Held funds only The state machine is the product. A request becomes an offer, becomes an Ordinary app bugs are annoying. Bugs that touch money are a different category, A double-charge is not resolved by correcting the code — the money has already This changes how you write things. Every money-moving operation has to be None of this is exotic. All of it is the difference between a bug you fix and a Everything above applies to any escrow marketplace. Crossing a border adds Prices move while a deal is open, because currencies move. Customs and duty are The engineering lesson is that a design which assumes stability will spend the The title suggests architecture diagrams. The reality is that owning it end to When a delivery goes wrong, the question is not only what the code did. It is The other half is choosing what not to build. Every marketplace has an infinite Flutter for both apps, so one codebase covers iOS and Android on each side — keep as much behaviour as possible changeable , because you cannot hotfix your way out of a marketplace The thing I would tell someone starting one of these: you are not building Shpper is at shpper.com, and there is a longer case study on this site. Originally published at devshakib.jumyn.com. I write about Flutter, Dart and the parts of shipping that are genuinely awkward — and publish the packages that came out of them at pub.dev/publishers/jumyn.com.
Your Flutter 404 Page Is Probably Crashing, and Your Server Is Probably Lying About It
K M Shahriar Hossain
Someone sent me a screenshot of my own 404 page. Washed-out grey text on a light It was not a styling bug. The page was crashing before it could paint, and the The site is a Flutter web app with every route prerendered to a real HTML file. "rewrites": [ { "source": "**", "destination": "/404.html" } ] That looks right. It is not, and the reason is worth internalising: a Firebase That is what a rewrite is — serve this other 200 OK with a page that said "Page not found". Browsers do not care. Crawlers care a great deal. A 200 means "this is a real /wp-admin was eligible to be indexed as a real page. This is the soft 404, looks correct. The fix is to delete the catch-all rather than repoint it. With every real route 404.html with an actual 404 status. One caveat that will bite you if your app has client-only routes. My admin panel "rewrites": [ { "source": "/your-client-only-path/**", "destination": "/index.html" } ] Scoped rewrites for the routes that genuinely need them; no catch-all; real 404s Fixing the status code is what made me actually look at the page, and that is My prerendered HTML carries the page's text in the DOM, clipped to a single The console had it: GoError: There is no GoRouterState above the current context. This method should only be called under the sub tree of a RouteBase.builder. Here is the chain. errorBuilder renders my NotFoundPage. That page uses the final current = GoRouterState.of(context).uri.path; On every real route that is fine. On the 404 page it throws, because errorBuilder renders outside any RouteBase.builder — there is no route GoRouterState to inherit. The instinct is maybeOf. In go_router 17 there is no GoRouterState.maybeOf. of() throws unconditionally; there is no nullable variant to fall back to. So the next instinct is to ask the router itself, which definitely sits above current = GoRouter.of(context).state.uri.path; // also throws I tried exactly this, and it fails too — differently, which is what makes it GoRouter.state reads matches.last on the current match list, and that list is empty, so you get a StateError: Bad state: . The accessor fails for precisely the reason you are on the 404 page Both router-side answers are dead ends. But the browser knows the path regardless String current; try { current = GoRouterState.of(context).uri.path; } catch (_) { current = Uri.base.path; } The broad catch is deliberate, and I would defend it specifically here. Nothing highlights on a 404, which is correct: no nav item corresponds to a page Because the two bugs concealed each other. The 404 page had been broken for The status-code fix did not cause the crash. It made someone look at the page, Two habits fall out of this. Check your 404 page's status code, not just its — curl -o /dev/null -w '%{http_code}' https://yoursite/nonsense actually load your , because it is the one page in Originally published at devshakib.jumyn.com. I write about Flutter, Dart and the parts of shipping that are genuinely awkward — and publish the packages that came out of them at pub.dev/publishers/jumyn.com.
A Squarified Treemap by Hand, Because Charting Packages Cannot Drill Down
K M Shahriar Hossain
Helm's storage tool shows your disk as a treemap: every folder a rectangle, I drew it by hand. Not because the packages are bad, but because the thing that Search for a Flutter treemap and you will find several that work. Hand them a A disk browser needs four things beyond that, and each one reaches into the Hit-testing that returns the node, not a coordinate. A tap has to resolve to which folder, at whatever depth you are currently at. Navigation as a first-class state. Diving into a rectangle re-lays out the entire canvas from a new root, and the breadcrumb has to be able to climb back. Labels that adapt. A rectangle 400 px wide gets a name and a size. One 20 px wide gets nothing, because a clipped half-word is worse than blank space. Layout over a subtree, not a list. The input is not fifty values, it is a tree with a million nodes, and you lay out one level at a time. Any one of those is a fork of the package. All four means you are writing it The naive treemap slices the rectangle repeatedly along one axis. It is easy and The squarified algorithm keeps rectangles as close to square as it can. The idea improves the worst aspect That is the entire algorithm. Sort descending, accumulate greedily, close the Two implementation notes that cost me time: Sort descending or the greedy step is meaningless. The whole method assumes Guard against zero. Empty folders, and the remaining space after the last NaN in the layout. NaN Scanning a 347 GB volume walks several hundred thousand files. Two things keep Scan off the main isolate. Walking a filesystem is not CPU-heavy so much as Lay out one level at a time. The tree has a million nodes; the screen shows The second point is the one that also solves the label problem. Because you only The hardest part of Helm's storage tool is not the treemap. It is making the macOS reports purgeable space — snapshots and caches the system will reclaim So the categories have to be disjoint buckets that reconcile to the volume's For a dashboard, no — use a package. For anything where the treemap is the The reward is that it is genuinely the fastest way to answer "what is eating my Helm is free and MIT, and the treemap is in lib/tools/storage/ui/widgets/treemap.dart if you want to read it rather than github.com/devShakib015/helm. Originally published at devshakib.jumyn.com. I write about Flutter, Dart and the parts of shipping that are genuinely awkward — and publish the packages that came out of them at pub.dev/publishers/jumyn.com.
المنصة اللي جاية بعد الموبايل مش خيال علمي
Ahmed ElFirgany
المنصة اللي جاية بعد الموبايل مش خيال علمي — بتتبنى قدام عينينا دلوقتي. جوجل هتطلق أول نظارة AI ليها في ٢٠٢٦، سامسونج طلعت Galaxy AI Glasses بالفعل، وRayNeo عرضت جيل جديد بالتعاون مع Dolby وBang & Olufsen. تلات شركات عالمية بتتسابق في نفس السنة بالظبط — ده مش تجربة، ده بداية سباق منصة حقيقية. قضيت ٥ سنين أبني للموبايل. ولسه معتبرش نفسي خلصت، بس المنصة اللي بنيت عليها شغلي عمره كله بقى ليها منافس واقف في الصف جنبها. السؤال مش هل النظارات هتاخد مكان الموبايل. السؤال: مين من المطورين هيبقى جاهز لما اللحظة دي تيجي؟ إنت متابع المنصة الجاية دي، ولا لسه مركّز بس في اللي إنت فيه؟ الاصطناعي #نظاراتذكية #هندسة_الموبايل #Flutter
David Stark: Top High-Paying Roles
David Stark
👋 Hello Architects & Elite Engineers, The market is shifting. We are seeing a surge in MOBILE roles this week. We don't do "Easy Apply". Our internal gatekeeper just processed 200+ verified remote jobs from our partner network. To get these jobs, you must pass the architecture audit. Here are the Top 5 roles worth your time today.** 👇 Staff Software Engineer 🏢 Samsara | 💰 Competitive | 📍 Remote Could you walk us through your experience with this tech stack? Tech Stack: .samsara.com/ About the role: Samsara (NYSE: IOT) sits a... 👉 Apply & View Full Salary Senior Quality Engineer (Montevideo) 🏢 LawnStarter | 💰 Competitive | 📍 Remote Could you walk us through your experience with this tech stack? Tech Stack: This is a remote role for candidates located in Montevideo, Uruguay. <... 👉 Apply & View Full Salary Senior Quality Engineer (São Paulo) 🏢 LawnStarter | 💰 Competitive | 📍 Remote Could you walk us through your experience with this tech stack? Tech Stack: This is a remote role for candidates located in São Paulo, Brazil. </p... 👉 Apply & View Full Salary Senior Quality Engineer (Mexico City) 🏢 LawnStarter | 💰 Competitive | 📍 Remote Could you walk us through your experience with this tech stack? Tech Stack: This is a remote role for candidates located in Mexico City, Mexico. <p... 👉 Apply & View Full Salary Software engineer 🏢 Sticker Mule | 💰 Competitive | 📍 Remote Could you walk us through your experience with this tech stack? Tech Stack: .stickermule.com Sticker Mule is building the Internet's most lucrative commerce... 👉 Apply & View Full Salary 👉 View the full board of 50+ New Jobs here 🛑 Stop doing 7-round HR interviews. We hold direct contracts with hiring CTOs for high-ticket roles. Accept the architecture challenge, get your Instant AI Score, and bypass HR completely. 👉 Take the CTO Challenge
Saving a Real File From Flutter Web, Instead of Downloading Another Copy
K M Shahriar Hossain
Build an editor on Flutter Web. The user opens budget.csv, edits it, hits budget.csv in their Downloads folder. They edit again, save again: budget (1).csv. Again: budget (2).csv. Their real file — the one on their Desktop that they opened — has never been The File System Access API gives a page a real handle to a real file, with It is a genuine capability, gated properly: the user picks the file, the browser final file = await FileSystemAccess.openFile(); await file.write(bytes); // the same file, in place No download. No (1). The file on their Desktop now has their edits. The download-a-copy behaviour is not laziness on anyone's part. For most of the out: the page That is why <a download> and the blob-URL trick that every Flutter Web file-save Understanding that is what tells you the File System Access API is a genuinely The second half is what makes it feel like an application rather than a web page. Handles can be persisted. Store one, and after a page reload — or the next That single behaviour is the difference between "a web tool I paste things into" Handles are stored in IndexedDB — they are structured-cloneable objects, not On startup, look for a stored handle. If there is one, ask whether permission is still granted. If it is, open silently and show the document. If it is not, show one button: Reopen budget.csv. Step four is the honest version of "restore my session". You are not The same API grants handles to whole directories. That unlocks a different class For anything resembling an editor, that is the difference between a single-file This is where an honest package earns its keep, because the API is not Support is real but partial. Chrome, Edge and other Chromium browsers have if (await FileSystemAccess.isSupported) { // "Save" — writes in place } else { // "Download a copy" — the old behaviour, honestly labelled } Label the fallback accurately. A button that says Save and silently produces budget (3).csv is worse than a button that says Download a copy, because the Permission is per-handle and revocable. A write can fail because the user It needs a user gesture. The picker cannot be opened from a timer or an The temptation is to write the good path and add a fallback later. That produces A structure that works: define one interface with open, save and saveAs. The label matters more than it sounds. If the fallback button says Save and budget (3).csv, the app has lied about what it did. If it says Download a copy, the user understands the platform limitation immediately and Flutter Web is unusually good at the kind of app this unlocks — editors, It is also the gap people cite when they say Flutter Web "isn't ready for real Every time this API comes up someone asks whether a web page can now read their Every handle comes from a user gesture through the browser's own picker. A page cannot construct a handle to a path it names. Access is per-handle. Being granted budget.csv grants nothing about the folder it sits in, or any other file. The browser blocks sensitive locations — system directories, and in Chromium's case a maintained blocklist that includes things like the user's home root and library folders. Permission is revocable and is re-confirmed after a reload rather than granted permanently in the background. It requires a secure context. No HTTPS, no API. The design is closer to "the user hands your app a file" than to "your app gets file_system_access is on pub.dev — MIT, 160/160 It returns false from the capability check on browsers that cannot do this, Originally published at devshakib.jumyn.com. I write about Flutter, Dart and the parts of shipping that are genuinely awkward — and publish the packages that came out of them at pub.dev/publishers/jumyn.com.
Scrolling to an Index in a Flutter Lazy List, Without Building Everything Above It
K M Shahriar Hossain
You have a list of a million rows and you want to jump to row 842,013. ScrollController.jumpTo takes a pixel offset, not an index. To convert one Flutter ships no answer. The two packages that did are both dead: scrollable_positioned_list — archived by Google scroll_to_index — last published in 2022 Between them they still serve over a million downloads a month, which tells you scrollable_positioned_list built a second complete list, anchored at the It works. It is also why jumping felt the way it did: for the duration of the And it is why the package was hard to maintain. Two lists that must agree about Before the real answer, it is worth walking the approaches people try first, Fixed item extent. If every row is exactly 72 pixels, index 842,013 is at SliverFixedExtentList exists precisely for Estimate, jump, correct. Guess an average height, jump to the estimate, then after paint, so the user sees the wrong content first. ensureVisible on a GlobalKey. This works beautifully and only for items Build everything. A million ListTiles is a million elements, a million shrinkWrap: true quietly does to you in some nestings, which is why it has the Each of these is the sensible next idea after the previous one fails. The reason compute an offset that the Viewport can nominate a centre sliver via its center property. It is before the centre sliver lays out at negative scroll offset. That is the whole solution, once you see it. Split the list in two at the anchor index: everything before the anchor goes in one sliver, laid out backwards from zero into negative offsets the anchor and everything after it go in a second sliver, marked as the centre Now scroll offset zero is the anchor. Not "approximately the anchor once we Jumping to index 842,013 becomes: rebuild with the anchor set to 842,013, offset final controller = AnchoredListController(); AnchoredList.builder( controller: controller, itemCount: 1000000, itemBuilder: (context, index) => ListTile(title: Text('Item $index')), ); controller.jumpToIndex(842013); // same cost as jumping to item 3 One viewport, one set of children, no cross-fade. If nominating a centre sliver and laying content out at negative offsets sounds CustomScrollView exposes center as public API, and The insight this package contributes is not the primitive. It is noticing that is the target, there is no That is why the jump is O(1) rather than merely fast. It is not that the search There is a related problem the same structure solves for free. You are reading a chat, or a feed, or a log. New items arrive above where you ListView every insertion above your position pushes With a centre sliver, items above the anchor live at negative offsets. Inserting upwards, into more-negative territory. Your position is That is why the package is called anchored_list rather than something about Two features become straightforward that are usually quietly dropped. Deep linking into a list. A notification says "someone replied to your at that comment, and scrolling up from it works Restoring scroll position properly. Saving a pixel offset and restoring it index and restoring the anchor is exact — the user comes back to the Both of these usually get cut during estimation because "scroll to an arbitrary Honest limitations, because a list package that claims none is hiding some: Two slivers, not one. If you were relying on a single-sliver structure for something exotic, this changes it. Scrollbar geometry is estimated. A lazy list genuinely does not know its own total height, so the thumb size is a best guess that improves as more is measured. Every solution to this problem shares that limit, including the archived ones. The anchor is a rebuild, not an animation. jumpToIndex is instant by design. If you want a visible scroll across a million rows, that is a different feature and a much slower one — and one nobody actually wants, since a five-second animated scroll past 800,000 rows is not a better experience than arriving. Items above the anchor build as you scroll up, exactly as items below build as you scroll down. Jumping to index 842,013 and immediately flinging upward will build items in that direction — which is correct, but means the work is proportional to how far you scroll, not zero. If you are migrating from scrollable_positioned_list, the mental model changes is the origin". For the common case — put item N at the top — they express anchored_list is on pub.dev — MIT, no The repository has a demo that jumps around a million-row list while showing the Originally published at devshakib.jumyn.com. I write about Flutter, Dart and the parts of shipping that are genuinely awkward — and publish the packages that came out of them at pub.dev/publishers/jumyn.com.
Talking to Native: FFI, Pigeon, and Knowing Which One You Need
K M Shahriar Hossain
A MethodChannel typo cost us three days and a hotfix release, and the compiler never said a word. That's the whole story of Flutter native interop in one sentence: the easy path is a stringly-typed message bus that fails silently in the field, and almost everyone reaches for it first. Every Flutter developer's first brush with native code goes the same way. You need something the framework doesn't give you — a battery level, a hardware sensor, a C library your backend team already trusts — and the first search result says MethodChannel. You copy the snippet, wire up a stringly-typed channel name, and it works. Ship it. Then it grows. Six months later that one channel has fourteen methods, each one a switch on a string, each argument a Map<String, dynamic> you as-cast and pray over. At Shpper we had exactly this: a device channel that had quietly become the single largest source of crash-free-rate regressions in one of our apps. The regression that cost us the three days was a renamed method on the Kotlin side that nobody renamed on the Dart side — green build, green tests, MissingPluginException on real hardware two days after release. Not one of those crashes was catchable by the compiler, because we'd built the boundary out of strings. The lesson I keep relearning: MethodChannel is the default answer and it is usually the wrong one. This post is the decision framework I wish I'd had earlier: the three ways Flutter talks to native code, what each one actually costs, and how to pick before you write a line of glue. Flutter gives you three real ways to reach native code. They are not interchangeable, and picking the wrong one is where the pain comes from. dart:ffi — call C (and Rust, and anything with a C ABI) directly, in-process, synchronously. No serialization, no message passing, no platform thread. This is the fastest path and the one people reach for last. Pigeon — a code generator that turns a schema of Dart abstract classes into type-safe, generated method channels for you. Same transport as raw channels underneath, but the compiler now checks both sides. Raw MethodChannel / EventChannel — the hand-written message bus between Dart and the platform (Kotlin/Java, Swift/Obj-C). Async, dynamically typed, and manual on both ends. Here's the mental model I use. FFI is for code — you have a native function and you want to call it. Pigeon is for platform APIs — you need to talk to Android or iOS SDKs and want a typed contract. Raw channels are for the awkward middle: event streams, plugin ecosystems, and things Pigeon can't express yet. FFI Pigeon Raw MethodChannel Talks to C / Rust / C ABI Kotlin / Swift SDKs Kotlin / Swift SDKs Call style Synchronous Async (Future) Async (Future) Type safety Compile-time (C types) Compile-time (generated) None Serialization None (raw memory) Standard codec Standard codec Runs on Calling thread Platform thread Platform thread Best for Hot paths, existing C libs New platform integrations Streams, edge cases If you take one thing away: the interesting decision is between FFI and Pigeon. Raw channels are the fallback, not the starting point. Everything below is really about earning the confidence to not hand-write a channel by default. The problem with raw channels isn't that they don't work. They work fine on the happy path, which is exactly why they're dangerous — the cost is deferred to the moment you least want it. A MethodChannel is a BasicMessageChannel with a method-call codec bolted on, and that's all the safety you get: a string name and a bag of dynamically-typed arguments. Look at a typical hand-rolled channel: const _channel = MethodChannel('com.shpper/device'); Future<int> getBatteryLevel() async { final result = await _channel.invokeMethod('getBatteryLevel'); return result as int; // hope it's really an int } And the Kotlin side: channel.setMethodCallHandler { call, result -> when (call.method) { "getBatteryLevel" -> result.success(batteryLevel()) // typo "getBateryLevel" here? compiles fine, fails at runtime else -> result.notImplemented() } } Three failure modes are baked in and none of them are caught by a compiler: Stringly-typed dispatch. The method name is a string on both sides. Rename it on one side and you get a silent MissingPluginException in the field. Grep is your only "refactoring tool," and grep doesn't know the difference between a channel name and a comment. Untyped arguments. Everything crosses the boundary as Object?. You cast on the Dart side and cast again in Kotlin. Change an argument's shape — an int that becomes a long, a field that becomes nullable — and nothing warns you until a specific device tries it. Worse, the standard codec silently promotes small integers, so a value that's fine in the emulator can ClassCastException on a payload that happens to exceed 32 bits. Always async, even when it shouldn't be. Every call is a Future, even reading a constant. That async hop forces await into call
freeCodeCamp
15 条教程、指南与实践文章
How to Use Skills in Agentic Flutter Development: A Handbook for Devs
Atuoha Anthony
One of the biggest misconceptions about AI-assisted development is that using AI means giving up the engineering experience you've built over the years. It doesn't. You can take the architecture patte
How to Test Flutter Apps: Unit, Widget, Golden, and Integration Tests Explained
Gidudu Nicholas
The first time I was asked "what's your test coverage?" in a technical interview, I didn't have a good answer. I had shipped a couple of real Flutter apps by then. They worked and users were using the
Mobile Background Execution: iOS Background Modes, Android WorkManager, and Background Services in Dart
Oluwaseyi Fatunmole
Every mobile developer eventually hits the same wall: the app works perfectly when the user is looking at it. But the moment they press the home button, everything stops. A sync that should have compl
Chain of Responsibility Design Pattern: Decoupling Complex Business Rules, One Handler at a Time
Oluwaseyi Fatunmole
Every system, at some point, ends up with a function that nobody wants to touch. It starts small: a simple validation check, an if statement here, another there. Then requirements grow and more condit
How to Work with Material and Cupertino Decoupling in Flutter [Full Handbook]
Atuoha Anthony
Earlier this year, I published Decoupling Material and Cupertino in Flutter, which covered what was then a preview feature: Flutter's plan to separate the Material and Cupertino design libraries from
How to Automate Flutter Releases with Fastlane and GitHub Actions for Firebase App Distribution, Google Play, TestFlight, and App Store Connect
Atuoha Anthony
Picture this: it's 4pm on a Friday, and your team has just merged the last feature for the sprint. But your product manager asks for a new build on TestFlight by the end of the day so the client can r
Flutter Frontend Systems Design: How to Think Like a Senior Engineer in the AI Age
Jesutoni Aderibigbe
Systems design has always been treated as a backend problem. Ask a group of Flutter engineers what systems design means, and most will describe server architecture: load balancers, databases, and micr
How to Test AI Features in Flutter [Full Handbook]
Atuoha Anthony
You've spent two weeks building an AI assistant. The streaming chat looks beautiful, the system prompt is tight, and safety filters are configured. You demoed it to the team, and everyone was impresse
A Deep Dive into Behavioral Patterns: The Visitor Design Pattern and its Clean Operations Across Complex Object Structures
Oluwaseyi Fatunmole
There's a problem that shows up in almost every growing software system, and most developers don't even realize they're hitting it until the damage is already done. You have a set of objects: differen
Bluetooth Low Energy in Flutter: A Handbook for Devs
Nikheel Vishwas Savant
Most Flutter tutorials stop at network calls and REST APIs. The moment you need to talk to a physical device, a heart rate monitor, a smart bulb, a fitness tracker, an industrial sensor, or your own c
From RPC to gRPC: Understanding Remote Procedure Calls, Protocol Buffers, and Modern Distributed Systems Communication
Oluwaseyi Fatunmole
Every application, at some point, needs to talk to another system. A mobile app talks to a backend. A backend service talks to a payment gateway. An authentication service talks to a user service. A d
The Observer Design Pattern Handbook: Event-Driven Architecture & Domain-Driven Design in Dart
Oluwaseyi Fatunmole
Every application, at some point, has to deal with a fundamental challenge: something happens, and several other things need to react to it. A user logs in, and the app needs to save a token, cache th
How to Fix App Jank: A Practical Guide to Profiling Flutter Apps with DevTools
Gidudu Nicholas
Flutter makes it fast to build beautiful UIs. That speed is one of the framework's greatest strengths, but it also creates a subtle problem: performance issues are easy to introduce and difficult to f
How to Use Claude Code to Build Flutter Apps Faster — Best Practices for 2026
Jesutoni Aderibigbe
In early 2023, I was interning at a US-based company, long before agentic AI became part of everyday development. We had tools like ChatGPT, Gemini, and Copilot, but they were mostly chat interfaces:
Advanced Dart: Learn Asynchronous Programming with Streams, Isolates, and the Event Loop
Gidudu Nicholas
I had been writing Flutter apps for over a year before I actually understood how Dart handles concurrency. I knew how to use await. I knew FutureBuilder and StreamBuilder well enough to get things wor
Hacker News
20 条技术社区讨论与项目链接
Show HN: CocoCut – A zero-cloud, 1-second video diary engine built with Flutter
xcc3641
Article URL: https://cococut.app/en Comments URL: https://news.ycombinator.com/item?id=49582167 Points: 2 # Comments: 1
DartNative: Beyond the Limits of React Native and Flutter
iosephmagno
Hi React Native and Flutter devs! We’re launching DartNative, a cross-platform framework for Dart that aims to deliver a truly native look and feel on iOS and Android. Would love to hear what you think. https://x.com/iosemagno/status/2096288716721356974?s=46 Comments URL: https://news.ycombinator.com/item?id=49579471 Points: 1 # Comments: 0
GoEven – Free, ad-free group expense splitter built with Go, gRPC, and Flutter
Xainpro
Article URL: https://goeven.app Comments URL: https://news.ycombinator.com/item?id=49578979 Points: 2 # Comments: 0
Show HN: Flutter Starter A production-ready Flutter app boilerplate
Harish_0089
Article URL: https://github.com/GeekyAnts/flutter-starter Comments URL: https://news.ycombinator.com/item?id=49432329 Points: 3 # Comments: 0
Flutter_scene 0.21.0 runs 3D apps with Flutter GPU and Impeller
chem83
Article URL: https://xcancel.com/antibot/captcha Comments URL: https://news.ycombinator.com/item?id=49307343 Points: 1 # Comments: 0
Flet: Build cross-platform apps in Python, on top of Flutter
theanonymousone
Article URL: https://flet.dev/ Comments URL: https://news.ycombinator.com/item?id=49283154 Points: 1 # Comments: 0
Flutter 3.47
gumby271
Article URL: https://flutter.dev/blog/whats-new-in-flutter-3-47 Comments URL: https://news.ycombinator.com/item?id=49280061 Points: 207 # Comments: 214
I built a local 3D marketplace with pizza-style tracking in Flutter
Nearnook_dev
Article URL: https://play.google.com/store/apps/details?id=com.lahoucintiyar.nearnook&hl=en_US Comments URL: https://news.ycombinator.com/item?id=49277267 Points: 1 # Comments: 0
Openhare: AI-powered desktop SQL client. Cross-platform. Built with Flutter
thunderbong
Article URL: https://github.com/sjjian/openhare Comments URL: https://news.ycombinator.com/item?id=49276189 Points: 4 # Comments: 0
FieldFleet – self-hostable field operations built with Flutter and Supabase
iguardo
Article URL: https://taskfleetai.github.io/fieldfleet/ Comments URL: https://news.ycombinator.com/item?id=49262555 Points: 3 # Comments: 0
Flutter desktop apps can draw to multiple windows now
matthewkosarek
Article URL: https://www.youtube.com/watch?v=yXj6HGTgKX0 Comments URL: https://news.ycombinator.com/item?id=49243250 Points: 2 # Comments: 0
Denial WM: New Wayland Compositor with Flutter Directly Embedded
mikece
Article URL: https://www.phoronix.com/news/Denial-WM-Compositor Comments URL: https://news.ycombinator.com/item?id=49184965 Points: 4 # Comments: 0
Rejourney Flutter Analytics in Beta: Session Replay for Flutter GPU and Impeller
mrr7337
Article URL: https://rejourney.co/engineering/2026-08-01/flutter-sdk-open-beta Comments URL: https://news.ycombinator.com/item?id=49162055 Points: 1 # Comments: 0
I made Squirrel game with Flutter and Flame
dmvvilela
Article URL: https://danvilela.com/squirrel-up Comments URL: https://news.ycombinator.com/item?id=49137413 Points: 5 # Comments: 0
Kaisel – Routes as Values. Dart 3 Native Router for Flutter
TheWiggles
Article URL: https://kaisel.dev/ Comments URL: https://news.ycombinator.com/item?id=49135985 Points: 58 # Comments: 11
A LangGraph pipeline that generates compiling Flutter apps (with a repair loop)
m2magents
Article URL: https://github.com/carlosge492/app-generation-microservice Comments URL: https://news.ycombinator.com/item?id=49130994 Points: 1 # Comments: 0
Built a household organizer in Flutter – what would you improve?
mladenConcept
Article URL: https://apps.apple.com/us/app/roomli-shared-home-organizer/id6761788107 Comments URL: https://news.ycombinator.com/item?id=49102118 Points: 1 # Comments: 0
Show HN: Cross-Platform Flutter and React-Native Plugin – FFmpeg-Kit-Extended
akashskypatel
Full featured React-Native and Flutter plugin that lets you execute FFmpeg, FFprobe and FFplay commands without needing to deploy those executables. Get the full power of FFmpeg at native performance level. Includes support for 100+ external libraries with pre-bundled preset distributions for 24 different binaries distributed per platform with various included features plus the ability to deploy custom builds. https://github.com/akashskypatel/ffmpeg-kit-extended https://www.npmjs.com/package/ffmpeg-kit-extended https://pub.dev/packages/ffmpegkitextended_flutter Core features: - Cross-Platform Support: Works on Android, iOS, macOS, tvOS, Linux and Windows. -- Android: Full video playback support with native surface rendering. --- x86: x86 architecture is not supported due to its legacy status. -- iOS & macOS: High-performance video playback with CVPixelBuffer and Metal integration. -- iOS: Supports both physical devices and simulators. x86_64 architecture is not supported due to its legacy status. - FFmpeg, FFprobe & FFplay: Latest 8.1.2 API support for media manipulation, information retrieval, and audio/video playback. - Video Playback: Complete cross-platform video playback with unified surface API. - Real-time Streaming: Position and video dimension streams for live playback monitoring. - Asynchronous Execution: Run long-running tasks without blocking the UI thread. - Parallel Execution: Run multiple tasks in parallel. - Callback Support: detailed hooks for logs, statistics, and session completion. - Session Management: Full control over execution lifecycle (start, cancel, list). - Extensible: Designed to allow custom native library loading and configuration. - Full package Introspection API: Get detailed information about the package, including version, build date, and available muxers, demuxers, encoders, decoders, filters, etc. - Deploy Custom Builds: You can deploy custom builds of ffmpeg-kit-extended. See: https://github.com/akashskypatel/ffmpeg-kit-builders - Prebuilt Distributions: Supported pre-built bundle types are debug, base, full, audio, video, and video_hw. - Supported Licenses: supports both GPL and LGPL licenses Platform Support: Android (and Android TV) - Flutter & React-Native iOS (and Simulator) - Flutter & React-Native tvOS (and Simulator) - React-Native macOS - Flutter & React-Native Linux - Flutter Windows - Flutter & React-Native Flutter currently does not natively support tvOS, so tvOS support is not available for Flutter. React-native currently does not natively support Linux, so Linux support is not available for React-native. Demo : https://raw.githubusercontent.com/akashskypatel/ffmpeg-kit-e... Comments URL: https://news.ycombinator.com/item?id=49052579 Points: 2 # Comments: 0
The wall every Flutter builder hits, and the ways around it
raeddev
Article URL: https://nowa.dev/blog/why-we-built-our-own-flutter-runtime/ Comments URL: https://news.ycombinator.com/item?id=49004951 Points: 1 # Comments: 0
Show HN: Ranking 19 LLMs on Flutter code by compile pass & hidden-test pass-at-1
GeorgiKadrev
Article URL: https://nativevibe.dev/flutter-benchmark Comments URL: https://news.ycombinator.com/item?id=48920784 Points: 2 # Comments: 0
Medium
10 条Flutter 相关文章精选
Your Flutter App Is Twice as Big as It Needs to Be. Here’s How I Halve It.
Shikha
A to-do app should not be a 40MB download. But open your release build and there it is, fat and proud. The worst part? Most of that weight… Continue reading on CodeToDeploy »
Flutter Authentication Beyond CRUD Part 2 — Multi Request Refresh Token
Creative Thief
Handling Multiple Concurrent Requests with Token Refresh Continue reading on Medium »
How My Flutter App Knows the Weather Outside
Ankit Mehra
We use weather apps all the time but have you ever thought that how a Flutter app actually gets that weather information? Flutter doesn’t… Continue reading on Medium »
Why Flutter Uses Three Trees Instead of One?
Anusha C
Widget Tree. Element Tree. RenderObject Tree. Continue reading on Medium »
Flutter Authentication Beyond CRUD Part 1 — Single Request Token Refresh
Creative Thief
Handling authentication in a Flutter application is more than attaching an access token to an API request. Continue reading on Medium »
I Built a Flutter Localization QA Tool That Found 48 Bugs in a 200-Line App
Piyush Kumar
Your Flutter app can look perfect in English and still be broken for everyone else. Continue reading on Medium »
The Unspoken Realities of Integrating DRM in Cross-Platform Mobile Apps
Stanley Muyuga
Why Digital Rights Management (DRM) promises robust content security, but delivers engineering headaches, hardware lock-ins, and developer… Continue reading on Medium »
Feature-First Flutter Architecture That Works for Humans and AI Agents
Abdul Momin Sakib
Flutter projects often begin with a simple structure: models in one folder, services in another, screens somewhere else, and providers… Continue reading on Medium »
What Actually Happens When setState() Is Called?
Developer Hub
The method looks tiny. The machinery behind it is anything but. Continue reading on Flutter Hub »
Flutter Assets, Images & Fonts: pubspec.yaml Guide
Ravi Savaliya
Learn how to add Flutter assets, images, SVGs, and custom fonts with pubspec.yaml, plus practical fixes for common asset loading errors. Continue reading on Medium »
社区日榜讨论与资源
After 11 years in mobile development, where should I go next in the AI era?
/u/Character_Nebula_277
I'm a developer with 11 years of Android experience and 7 years of Flutter experience. I've been working with Flutter since its early days. Over the years, my work gradually moved beyond regular application development and more toward lower-level and performance-related areas. I've worked on things like Flutter internals, memory and rendering performance, Flutter + C/C++ and Flutter + Rust integrations, as well as some internal infrastructure and framework-level work. At several companies I've worked for, I ended up dealing with similar kinds of problems: redesigning or wrapping lifecycle systems, tracking down memory issues, solving rendering and performance problems, building custom UI behavior such as larger touch areas independent of visual size, and occasionally debugging issues around the Flutter Framework or Engine. For a long time, I believed the best way to stay competitive was to keep going deeper. It wasn't enough for me to know how to use Flutter. I wanted to understand why Flutter behaved the way it did. So I spent a lot of time trying to build technical depth and create a stronger technical moat for myself. But since AI coding tools became genuinely useful, I've started feeling a level of career anxiety that I didn't have before. A lot of problems that used to require years of experience can now be approached much faster by a less experienced developer working with AI. AI can help them navigate source code, trace call chains, identify likely causes, and even generate a reasonably good implementation. For experienced developers, the productivity improvement can be even more dramatic. In my own work, I feel like my productivity has at least doubled in many situations, and sometimes even more. And that's exactly what worries me. If one experienced developer with AI can do the work that previously required two or three developers, will companies still need the same number of mobile developers? I'm also starting to feel that some of the technical barriers I spent years building are becoming easier to cross. In the past, there were plenty of developers who could build application features. Far fewer understood the Framework level. Even fewer were comfortable with the Engine, memory, rendering, or Native/Rust integration. AI is now making it much easier for developers to move across at least part of those boundaries. So I've developed a strong feeling recently: I'm not worried that I'll suddenly lose my job tomorrow. I'm worried that the next time I leave my job, finding another mobile position at a similar level may be much harder than it used to be. Especially considering the current software job market in China, I'm starting to question whether continuing to invest heavily in deeper Flutter and Android knowledge still has the same return it once did. So I'd genuinely like to hear what other developers think. If you had already spent more than a decade in mobile development, where would you move next in the AI era? AI applications? AI infrastructure? On-device AI? Robotics / AI hardware? Embedded systems? Or would you stay in mobile development and gradually become more of an AI + client/mobile engineer? At this point, I'm no longer trying to figure out which programming language I should learn next. The question I'm really trying to answer is: Over the next 5–10 years, which technical areas are still worth investing deeply in for someone who already has more than a decade of software development experience? I'd especially like to hear from other long-time Android, iOS, or Flutter developers, or anyone who has already started making a similar transition. submitted by /u/Character_Nebula_277 [link] [comments]
No regrets migrating from react native (expo) to flutter!
/u/jaironlanda
hello flutter devs! migrating to flutter has been surprisingly awesome! my previous app was built with react native / expo, and honestly, i kind of regret choosing that stack. it took up a lot of space on my laptop, and the compilation and build process was often painfully slow. now i’m starting a new project with flutter, and so far, i’m really enjoying it. the compile times feel much faster, the development experience is pretty smooth, and i especially like having built-in support for unit testing. i can write some code, run a test, and quickly see if everything works as expected. still early in the project, but so far, flutter has been a really nice experience. curious to hear from other flutter devs. what do you like most about flutter? submitted by /u/jaironlanda [link] [comments]
From Flutter to Jaspr
/u/eibaan
I've a Flutter web app which could benefit from the high fidelity CSS-controlled text display of a real web app. So, why not try to use Jaspr instead? I was under the impression that Jaspr tries to imitate the Flutter API including using Widget as the base class, but it's using Component which requires some changes. Still, no biggy. Promising. First impression was poor. I'd have preferred to install it via homebrew and not dart install which requires me to modify the PATH and which is yet another installer I have to make sure I don't forget to uninstall. But the main problem was that it doesn't work out of the box. jaspr serve throws errors. I had to downgrade the build_web_compilers to 4.8.5 to make it build. It also configured an ancient version of Dart which I changed to 3.13. I chose SPA as start template, perhaps it's better if you try to build a static side or server rendered pages. Now, the counter example worked as expected. The page could use a little designer love, though. The generated source code was easy enough to understand and jaspr serve supports hot-reloading, so I continued. Next, I tested how easy it is for Codex to create a more complex app. Will it struggle with not-flutter sources? So I asked it to create a chess app, for two human players, including a timer. And GPT Sol delivered. So AI seems to have no problem. Great. Next, I asked Codex to port my app. That worked in principle, but it had trouble to recreate the fidelity of the UI. Like most others, I used Chadcn/ui as my inspiration and Codex wasn't able to translate the themed Material widgets into Jaspr components. Might be an AI thing, but it didn't understand to take border into account. I had to ask for a lot of tweaks and would have preferred actually use Chadcn/ui or at least Tailwind. Theoretically, this should be possible and I think, there are packages on pub.dev which already attempted to do so. That might be worth more exploring. Instead of some random UI package that has a high risk of being unmaintained AI slop, an official port of chadcn/ui would be a great feature IMHO. My code cloc's at ~4000 lines (110 KB) with 1.8 MB in build/jaspr. That… a lot. There's a package folder that looks like it shouldn't be there with 1.3 MB. So I assume, my app has a size of 0.5 MB. For comparison, I asked Codex to recreate the same app using React. That's a home game for the AI which one-shotted the task. The result cloc's at ~1000 lines (72 KB), so using Dart instead of JS+JSX is a high price you must be willing to pay. The distribution size is 0.3 MB. I don't really mind that 200 KB dist overhead because of Dart. But I dislike the larger codebase. I figure, all those things add up. In React, I simply use style={{ width: size, height: size }} while in Jaspr, this becomes styles: Styles( width: .pixels(size.toDouble()), height: .pixels(size.toDouble()), ), Right now, I'm still undecided whether to proceed with Jaspr (because I like working with Dart) to switch to React (because the AI will deal with languages and syntax anyhow), but call me at least impressed. Has anybody else switch from Flutter to Jaspr for web apps? What's the experience with larger code bases, say 30Klocs? submitted by /u/eibaan [link] [comments]
document_pip: live Flutter widgets in a real always-on-top OS window, from Flutter Web
/u/Shakib015
Document Picture-in-Picture is a browser API that gives you an actual operating-system window — not an overlay inside your page. It floats above every other application and keeps running when you switch tabs. Chrome and Edge have had it since 116, Firefox shipped it in 151. I couldn't find anything reaching it from Flutter, so I wrote a package: https://pub.dev/packages/document_pip (MIT, 160/160 on pub.dev) void main() => runWidget( DocumentPipApp( main: (context) => const MaterialApp(home: Player()), popOut: (context) => const MaterialApp(home: MiniPlayer()), ), ); final window = await DocumentPip.open(width: 380, height: 210); The browser API is about four lines. Everything difficult was on the Flutter side, and it all traces to one thing: the engine assumes there is exactly one window. Three things break when there are two, and all three fail silently. 1. The pop-out freezes the instant you switch tabs. Chromium keeps painting a picture-in-picture opener at full rate in a background tab, but still reports the page hidden. Flutter's web engine turns that into AppLifecycleState.hidden, SchedulerBinding clears framesEnabled, and scheduleFrame() returns early forever. Measured: 302 browser animation frames in 2.5s against 0 Flutter frames in 3s. scheduleForcedFrame() ignores framesEnabled, so the root re-arms it for exactly as long as the page is hidden and a window is open. Firefox doesn't have the problem — it keeps reporting the opener visible — so the workaround is gated on the failure rather than on the browser. 2. The keyboard is dead in the pop-out, but typing still works. KeyboardBinding is a singleton bound to the opener's window, so a separate browsing context isn't on the propagation path: Shortcuts, Actions, Focus.onKeyEvent, HardwareKeyboard, Escape and Tab traversal all get nothing. Plain typing keeps working because the browser routes characters to the focused element natively, which is exactly what makes this easy to miss. The package replays key and selection events into the opener. 3. A package can't turn multi-view on. Only the JS app object returned by engine.runApp() can add a view — dart:ui_web exposes the views read-only — so it has to be reachable from your bootstrap. That means runWidget instead of runApp, plus a few lines in flutter_bootstrap.js. Both are one-time and the errors name the fix. Desktop Chromium and Firefox 151+ only. Safari and Firefox for Android have no implementation, and isSupported is a feature detect so you can gate the control on it. It compiles on every platform, so adding it won't break a cross-platform build. Longer writeup with the measurements: https://devshakib.jumyn.com/blog/flutter-assumes-there-is-only-one-window Happy to answer anything about the multi-view side — that part is under-documented and I burned a lot of time on it. submitted by /u/Shakib015 [link] [comments]
Tackling the classic Shopping Cart problem with BlocSignal + Fast Immutable Collections (with hydration and undo/redo)
/u/RandalSchwartz
I’ve been working through various common Flutter architecture problems to see how BlocSignal handles them in practice. After putting together the infinite scroll a few days ago, I decided to tackle the shopping cart... everyone's favorite CS final exam problem. One thing that always annoyed me about shopping cart tutorials is how mutable lists cause subtle state bugs (missed rebuilds from identical references, or corrupted undo stacks). I wanted to see how clean we could make it using Marcelo Glasberg’s Fast Immutable Collections (package:fast_immutable_collections) alongside Dart 3 records. The result turned out surprisingly concise with almost zero boilerplate. And just to push the pattern a bit further, I threw in offline persistence (via bloc_signals_hydrate) and time-travel undo/redo (via bloc_signals_replay) to see if the state would remain rock-solid. Yes, I had Antigravity help me write and test the code, but I think the resulting pattern speaks for itself. You can check out the full runnable example and test suite here: https://github.com/RandalSchwartz/BlocSignal/tree/main/examples/fic_shopping_cart Curious to hear what folks think about pairing records with FIC for collection state like this, or how you typically handle cart immutability in your own setups. submitted by /u/RandalSchwartz [link] [comments]
React Native or Flutter for a Superapp host app? Looking for stack recommendations and experiences.
/u/SofiaDaFnck
Hi everyone, I'm a mobile dev currently tasked with building a superapp. Since I don't have prior experience with superapp architecture, I'm a bit unsure about choosing the right tech stack for the host app and the bridge/integration layer for mini-apps. Since I’m proficient in both React Native and Flutter, I’d strongly prefer sticking to a cross-platform solution rather than going fully native. If you were to build a superapp today, what tech stack / combo would you go with? Would love to hear your recommendations and real-world experiences! submitted by /u/SofiaDaFnck [link] [comments]
I built a Flutter localization test sweep that found 48 issues in a 200-line app
/u/Key-Communication865
I kept running into localization issues that looked fine in English but broke in other languages: text overflow, RTL spacing, missing ARB keys, and untranslated strings. So I built LocaleSweep, an open-source Flutter QA utility that runs a widget test across locales, text scales, viewports, and brightness modes. I tested it against a small three-screen app across eight locales. That created 192 variants, and it found 48 issues, including: overflow at 2× text scale missing Arabic and Hebrew ARB keys placeholder mismatches untranslated Japanese strings RTL padding problems I’m the author, so consider this a transparent self-promo, but I’d genuinely love feedback from Flutter developers: what checks would make this useful in your CI workflow? Article: https://medium.com/@piyushhh01/i-built-a-flutter-localization-qa-tool-that-found-48-bugs-in-a-200-line-app-a3ffcd7800ca Package: https://pub.dev/packages/locale_sweep Source: https://github.com/Piyushhhhh/locale_sweep submitted by /u/Key-Communication865 [link] [comments]
I’m a developer who keeps overthinking every app idea until I convince myself it won’t work 😂
/u/No_Dealer21
So I’m trying something different tell me about a problem you wish had an app/solution. Doesn’t have to be a million-dollar idea. Just something annoying you deal with regularly. I might actually build one of the ideas here. 👀 submitted by /u/No_Dealer21 [link] [comments]
Is flutter even planning for liquid glass or not bruh?
/u/Reasonable-Pass-4642
is there any solution to this for now? is there any reliable package? i really want the liquid glass bottom navbar in my app ugh, but flutter damn their work on ios 18 was very good with cupertio widgets, but what happened now? are they even planning for ios 26+ or not? submitted by /u/Reasonable-Pass-4642 [link] [comments]