今日已更新 84 条资讯 | 累计 37333 条内容
关于我们

标签:#flu

找到 45 篇相关文章

AI 资讯

Mastering Hive in Flutter: A Step by Step Beginner's Guide to Fast Local Storage

Introduction When building a Flutter application, you'll often need to store data on the user's device. For example: Saving user preferences Storing login information Caching API responses Creating offline applications Building note-taking or to-do apps While there are several local storage solutions available, Hive is one of the fastest and easiest local storage for Flutter developers. In this tutorial, you'll learn Hive from scratch by building a simple example. No prior database knowledge is required. What is Hive? Hive is a lightweight, NoSQL database written entirely in Dart. It stores data directly on the device, making it perfect for Flutter applications. Why use Hive? Extremely fast Works offline No native platform code required Simple API Easy to learn Great for small and medium-sized applications Think of Hive as a collection of boxes where each box stores your application's data. Hive ├── User Box ├── Settings Box ├── Notes Box └── Products Box Each Box is similar to a table in traditional databases. Step 1: Create a Flutter Project Create a new Flutter project. flutter create hive_demo Open the project. cd hive_demo Step 2: Install Hive Open pubspec.yaml and add the following packages. dependencies : flutter : sdk : flutter hive : ^2.2.3 hive_flutter : ^1.1.0 Then install them. flutter pub get Step 3: Initialize Hive Before using Hive, initialize it inside main() . import 'package:flutter/material.dart' ; import 'package:hive_flutter/hive_flutter.dart' ; void main () async { WidgetsFlutterBinding . ensureInitialized (); await Hive . initFlutter (); await Hive . openBox ( 'settings' ); runApp ( const MyApp ()); } Here we open a box called settings . Step 4: Understanding Boxes A Box is where Hive stores data. Imagine this box: Settings Box theme -> dark username -> Alex loggedIn -> true Keys are on the left. Values are on the right. Step 5: Save Data Saving data is incredibly simple. var box = Hive . box ( 'settings' ); box . put ( 'username' , 'John' );

2026-07-30 原文 →
AI 资讯

Displaying async values in Flutter

The build method in Flutter widgets is synchronous. That means it doesn’t like to wait for anything. But sometimes, we need to wait for a value to arrive in order to display it. Let’s think of a simple weather app that displays only the temperature of a city. The app needs to make a request to the backend, get the temperature value, and finally display it. It will have to wait for a response from the backend, but as we discussed, the build method does not like to wait for anything. So how do we solve this issue? Enter: FutureBuilder . FutureBuilder takes a value of type Future and displays widgets until it is resolved. In fact, we can specify which widgets to display not only while loading but also when an error occurs. Let’s see how we can use FutureBuilder in a simple app. First, create an app in a directory of your choice: flutter create future_builder --platforms = macos You can choose whichever platform you want. Open the project in your preferred IDE, and navigate to lib/main.dart . Replace the entire content of the file with the following: import 'package:flutter/material.dart' ; void main () { runApp ( const MyApp ()); } class MyApp extends StatelessWidget { const MyApp ({ super . key }); @override Widget build ( BuildContext context ) { return MaterialApp ( home: const MyHomePage ()); } } class MyHomePage extends StatelessWidget { const MyHomePage ({ super . key }); Future < int > _getTemperature () async { await Future . delayed ( Duration ( seconds: 3 )); // Dummy delay of three seconds. return 25 ; } Future < int > _getTemperatureError () async { await Future . delayed ( Duration ( seconds: 3 )); throw Exception ( 'An error occurred while retrieving the temperature value.' ); } Future < int ? > _getTemperatureEmpty () async { await Future . delayed ( Duration ( seconds: 3 )); return null ; } @override Widget build ( BuildContext context ) { return Scaffold ( body: Center ( child: FutureBuilder ( future: _getTemperature (), builder: ( context , snapshot )

2026-07-29 原文 →
AI 资讯

How to Review AI-Generated Flutter Code (Before It Breaks Production)

Every unsupervised AI agent we've reviewed that wrote Flutter code made the same seven mistakes. These aren't typos or stylistic differences. They're structural failures that compound—bad state management plus missing tests plus hardcoded colors means the codebase becomes expensive to theme, hard to test, and impossible to maintain at scale. Here's a small one to set the tone: a developer asked an agent to implement a GET request to an external service in a Dart project. The agent's solution was to shell out to curl via Process.run and parse the stdout. Not package:http . Not dio . Not even dart:io 's own HttpClient . A subprocess call to a CLI tool, inside a language that's had first-class HTTP clients since Dart 1.0. That one is worth sitting with, because it's not really a Flutter problem — it's the whole pattern in miniature. The agent wasn't "wrong" that curl can make a GET request. It optimized for "this pattern appears constantly in training data" over "this is the idiomatic way to do it in the language I'm currently writing." Bash and curl show up in approximately every tutorial, README, and Stack Overflow answer ever written. package:http shows up in Dart-specific docs. Given no other constraint, the agent reached for the statistically dominant pattern, not the contextually correct one. The seven gaps below are the same failure mode, just less obvious than "shells out to curl." Here's what we found, with real code examples and the fixes that work. 1. Recomputing Derived State The Problem: Agents recalculate the same values across multiple locations instead of maintaining one source of truth. Imagine a checkout flow where the cart total is computed three separate ways: In the checkout page: (items.sum + tax) - discount In the footer: items.sum - discount + tax In the order summary: (items.sum - discount) * (1 + taxRate) Different calculations. Same semantic meaning. One will break first. The Fix: Derive values once in the state layer using streams. Let all w

2026-07-28 原文 →
AI 资讯

Switching Tracks in BlocSignal: The Universal State Switchyard for BLoC, Riverpod, and Provider

By Randal L. Schwartz, and a few million TPU cycles Motto: "With the rigor of Bloc and the flex and speed of Signal" Why You Don't Have to Tear Up Your Codebase to Enjoy the Speed of Synchronous Signals If you have followed my talks, articles, or comments in the Flutter community over the years, you know I have been a strong advocate for Riverpod . Riverpod solved many of the fundamental global-state scoping issues inherent in classic InheritedWidget patterns, providing compile-safe dependency injection and clean state isolation. However, as the Flutter ecosystem evolved toward Riverpod 3 , I grew increasingly wary of the direction being pushed: a heavy reliance on mandatory code generation ( @riverpod annotations, build_runner, macros). Code generation introduces build-step friction, bloats compile times, and makes debugging generated syntax opaque. On the other side of the tracks sat BLoC . While I appreciated BLoC's structured, predictable event-to-state machine pattern ( on<Event> ), I was never a big fan of classic BLoC's reliance on underlying Dart Streams . Streams operate asynchronously via microtask queues—introducing subtle frame-rendering latency—and require extensive stream-transformer ceremony for simple state updates. Then came Signals (specifically Rody Davis's signals package). Signals brought raw speed, zero microtask overhead, fine-grained composable reactivity, and pure Dart portability. That realization birthed BlocSignal : combining BLoC's disciplined, enterprise event-state architecture with Signals' synchronous reactivity. And more importantly, it solved the single biggest pain point in Flutter development: the migration trap . 🚂 The Core Metaphor: "Switching Tracks in BlocSignal" In Flutter development, choosing a state management tool often feels like choosing a railroad company. If your team built an application on package:provider or flutter_bloc and wants to adopt Riverpod or Signals, traditional wisdom dictates a nightmare: tearing up al

2026-07-27 原文 →
AI 资讯

PhilBuilder vs voltbuilder

The problem Every time I needed to hand someone a quick installable build — a client, a tester, myself on a different machine — I had to either keep a full local toolchain ready (Android Studio, Flutter SDK, Visual Studio...) or spend 20 minutes reinstalling one just for a single build. So I built PhilBuilder : upload a zipped source project, pick a platform, get back an installable app. No local setup required. 🔗 Try it: https://philbuilder.netlify.app What it does You upload a .zip of your project. The tool: Auto-detects the project type (React, Vue, Flutter, React Native, Kotlin, .NET MAUI, Python, Go, Godot, and 14 others — 22 combinations total) Builds it on remote CI Gives you a download link for an APK, AAB, or Windows .exe No account needed for occasional use (3 builds/day). A free account bumps that to 10/day. How it's built The stack is intentionally simple: Frontend : a single static HTML file, no framework, no build step Backend : a Cloudflare Worker handling auth, rate limiting, and dispatching builds Build execution : GitHub Actions — one big workflow with per-language jobs (Cordova for web frameworks, Capacitor for modern web, native Gradle for Kotlin/Java, dotnet publish for MAUI, flutter build for Flutter, briefcase for Python, gomobile for Go, etc.) Storage : Cloudflare R2 for source zips and build artifacts The auto-detection logic walks the extracted zip looking for telltale files — pubspec.yaml → Flutter, *.csproj → .NET MAUI, capacitor.config.* or a @capacitor/core dependency → Capacitor, build.gradle without package.json → native Kotlin/Java, and so on — with fallbacks down to plain HTML. Some technical details Signing : for Android release builds, it can auto-generate a keystore (and let you download it afterward — losing it means you can never update your app on Play Store again, so this is clearly flagged) or accept an uploaded one. Windows builds : this is the newest addition. Flutter and .NET MAUI need windows-latest runners; Go cross-com

2026-07-26 原文 →
AI 资讯

Validate Kubernetes Manifests with Flux Schema

If you run GitOps with Flux, a broken manifest usually gets caught the slow way: it merges, the reconciler chokes, and you find out from a failing Kustomization. Flux Schema, the plugin that shipped with Flux 2.9, moves that check left into CI. It validates every YAML document against JSON Schema and CEL rules using the same evaluation logic as the Kubernetes API server, so a bad field fails the pull request instead of the cluster. Install and run it Flux Schema is a CLI plugin, not part of the core binary. Install it through the plugin system: $ flux plugin install schema $ flux schema --help Pin a version in CI so a new release never changes your gate's behavior mid-sprint: $ flux plugin install schema@0.5.0 Point it at a directory of manifests and it validates each document: $ flux schema validate ./manifests It ships with built-in schemas for Kubernetes, OpenShift, Gateway API, and the Flux CRDs, so a fresh install already knows your HelmRelease and Kustomization kinds without any setup. Strict validation flags unknown fields, wrong types, and missing required properties as hard errors, which catches the typos kubectl apply --dry-run=client quietly ignores. What CEL adds over plain schema checks JSON Schema catches shape problems: a string where an int belongs, a misspelled key. CEL rules catch logic problems. Because Flux Schema runs the x-kubernetes-validations rules embedded in CRDs through the same CEL engine the API server uses, a manifest that violates a cross-field constraint (say, a replica count that must stay below a limit, or two mutually exclusive fields both set) fails in CI with the exact message the cluster would have returned. You are testing against the real admission logic, not a stale copy of it. Wire it into a config file Drop a .fluxschema.yml at your repo root to control what gets checked. The file uses the schema.plugin.fluxcd.io/v1beta1 API and a Config kind: apiVersion : schema.plugin.fluxcd.io/v1beta1 kind : Config skipKind : - Secret s

2026-07-26 原文 →
AI 资讯

Architecting RoutePe Auto: Building a Scalable Transport Management Software with Laravel, React, Flutter and MySQL

Modern logistics is built on time-sensitive operations, yet traditional freight procurement suffers from friction. Legacy systems depend heavily on fragmented offline negotiations, opaque spot market prices, manual Lorry Receipt (LR) tracking, and coordination gaps between warehouse controllers and field drivers.To eliminate these operational bottlenecks, RoutePe Auto was engineered as a high-throughput Transport Management Software . The platform unites real-time spot bidding, pay-per-tender corporate procurement, vehicle discovery, automated freight billing, and live multi-point tracking into a unified ecosystem. Here is an architectural breakdown of how RoutePe Auto was designed using Laravel on the backend, React on the web frontend, a native Mobile App , and MySQL for transactional integrity. Architecture Overview ┌──────────────────────────┐ │ React Web Dashboard │ │ (Shippers / Logistics) │ └────────────┬─────────────┘ │ REST / WebSockets │ ┌──────────────────┐ ┌────────────▼─────────────┐ ┌──────────────────┐ │ Mobile App │◄────►│ Laravel API Gateway │◄────►│ MySQL Database │ │(Drivers/Fleet) │ │ & Execution Core │ │ (ACID Transactions) └──────────────────┘ └────────────┬─────────────┘ └──────────────────┘ │ ┌──────▼──────┐ │ Redis Queue │ └─────────────┘ The system operates across three tiers:The Web App Layer: Built with React, offering enterprise shippers a dynamic workspace to broadcast loads, review bids, manage tenders, and monitor active routes. The Field Execution Layer: A dedicated Mobile App for drivers and fleet operators, streaming real-time location updates, uploading electronic Proof of Delivery (ePOD) signatures, and receiving job dispatches. The Core Engine: A robust Laravel REST API backend handling business logic, asynchronous task dispatching, document generation, and balance ledger management against a relational MySQL store.Database Design in MySQLA core requirement for any Transport Management Software is strict transactional integrity.

2026-07-25 原文 →
AI 资讯

I Built a 3D Game in Flutter — With No Game Engine

Everyone says the same thing: Flutter is for apps, not games. So I decided to find out where that's actually true — by building a 3D endless runner in Flutter. From scratch. No Unity, no Unreal, no game engine at all. Just Dart and Flutter's own rendering stack. It runs in your browser right now: ▶️ Play it live (desktop, keyboard controls — A / D to switch lanes, Space to jump). Here's how it works, and what building it taught me about how far Flutter can actually go. The stack: Flutter GPU + flutter_scene The whole thing sits on two pieces most Flutter developers have never touched: Flutter GPU — a low-level rendering API that talks almost directly to the GPU through Impeller (the engine that replaced Skia). This is what makes real-time 3D possible at all. flutter_scene — a higher-level 3D scene API on top of Flutter GPU. It gives you the building blocks a game needs: a scene graph of nodes , a perspective camera , meshes, and glTF model loading. You build a tree of nodes, point a camera at it, and render it every frame inside a normal Flutter widget. That last part still surprises me — the 3D world is just a CustomPaint -style surface living inside an otherwise ordinary Flutter app. Faking an infinite world with a handful of objects An "endless" runner obviously can't build an endless world — you'd run out of memory in seconds. The trick is object pooling : you keep a small pool of track segments and obstacles, and as they scroll past the camera behind the player, you recycle them back to the front with new positions. The player never actually moves forward. The world moves toward the player , and a fixed number of segments cycle forever. Same idea for obstacles and coins. It means the game runs at a constant, tiny memory footprint — which is exactly what keeps it smooth on weaker devices. The parts that were genuinely hard Collision that feels fair. Detecting a collision is easy. Making it feel right is not. Too strict and the player rages at hits that "clearly

2026-07-25 原文 →
AI 资讯

Customizable workout app

If you are like me, then you have also tried to change a specific thing in your workout plan that your app of choice didn't support. Well I'm trying to fix that issue with a workout app in which you'll be able to customize pretty much everything (WIP). Building the thing in Flutter to have mobile (starting with Android) and web. The web app is live! If you work out and have tried similar apps before, your feedback would be gold. But really any feedback is appreciated. I also found that finding the required 12 people with an Android phone for closed testing on Google Play Console was more difficult than anticipated. So if you'd be interested in that, hit me up at dev@notes.fitness ! Gym Notes — A Customizable Workout Logbook for Strength Training A free, customizable workout logbook that tracks exercises, sets, reps, and weights. Built-in training plans with automatic progression. gym.notes.fitness

2026-07-19 原文 →
AI 资讯

Flutter State Management in 2026: Riverpod vs Bloc vs Provider in Production

Flutter State Management in 2026: Riverpod vs Bloc vs Provider in Production Every Flutter team eventually hits the same wall. The app works, the demo looks great, and then somewhere around screen thirty the setState calls start colliding with each other, a widget rebuilds three times for one tap, and nobody on the team can explain why a loading spinner is stuck on a screen the user already navigated away from. That's the moment state management stops being a "nice to have" architectural decision and becomes the thing standing between you and a shippable product. We've built and maintained Flutter apps across fintech, e-commerce, logistics, and healthcare — different domains, wildly different feature sets, but the same recurring question from every engineering lead we work with: Riverpod, Bloc, or Provider? There's no shortage of opinions online, and most of them are shallow — "Bloc is too much boilerplate," "Riverpod is the future," "Provider is basically deprecated." None of that is useful when you're the one who has to live with the decision for the next two years of feature work. This is a practitioner's comparison, not a popularity contest. We'll walk through what each of these actually does under the hood, where each one falls apart in production, and how we decide which one to reach for on a new project. Why state management is the architecture decision that matters most In most application frameworks, state management is one of several important decisions. In Flutter, it's disproportionately important, because Flutter's entire rendering model is built around widget rebuilds driven by state changes. Get state management wrong and you don't just get messy code — you get a slow app, because unnecessary rebuilds are a real performance cost, not just an aesthetic one. There are three problems every state management approach in Flutter has to solve: Where does state live , and how does a widget deep in the tree access state that was created somewhere else? How do

2026-07-17 原文 →
AI 资讯

Automating an app with no DOM: driving Flutter/canvas editors with coordinates only

In my last post I said that for normal HTML pages, element-based automation ( find / read_page ) beats coordinates every time. This post is about the apps where that advice is useless. Flutter Web apps. Canvas-rendered editors. Every button and panel you can see on screen doesn't exist in the DOM — it's all pixels painted onto a single canvas. find returns nothing. read_page 's accessibility tree is effectively empty. I got Claude to drive the Rive editor (an animation tool built with Flutter) all the way through selecting assets and exporting them. Here's the procedure that survived contact with reality. Step zero: confirm you're actually in this situation Coordinate automation is fragile, so you should only accept it after ruling out the alternative. The test is quick: run read_page . If the visible UI has almost no corresponding nodes, you're looking at a canvas-rendered app, and coordinates are the only interface you have. The four rules 1. Wait for the window size to settle before anything else Same failure mode as my previous post: right after load, the viewport hasn't reached its final width (I measured 1664→1920 over 2–3 seconds), and clicks based on an early screenshot land to the right of the target. Read innerWidth via javascript_tool twice; only proceed when two consecutive reads match. But matching innerWidth alone isn't enough — also confirm devicePixelRatio hasn't changed since the screenshot you're about to act on (a follow-up to my previous post surfaced this: when DPI or scaling changes, the whole coordinate space rescales the same way, but the new values stabilize immediately, so an innerWidth -only check can't catch it). Canvas apps deserve extra paranoia here, because there is no element-based fallback when a click misses. 2. Read text by zooming, not by extracting Text painted on canvas can't be pulled out of the DOM. To read a menu item or panel label, zoom into that region and read the enlarged screenshot as an image. Full-page screenshots ma

2026-07-14 原文 →
AI 资讯

I built on-device workout rep counting in Flutter — here's what actually worked

I'm building TrainWiz , a Flutter app that turns real exercise into a pet-raising game: you do squats or push-ups, your phone counts the reps, and a little creature levels up and evolves. The core technical problem sounds trivial and absolutely is not: count reps from the camera, on-device, without uploading a single frame. Here's what broke along the way, and what finally worked. Why on-device Two reasons: privacy and latency. A fitness camera that streams your body to a server is a non-starter for most people, and rep feedback has to feel instant or the whole "game" loop dies. So everything runs locally with tflite_flutter + an on-device pose model — no footage ever leaves the phone. Naive attempt #1: joint-angle thresholds The obvious approach: track the knee angle, count a rep when it dips below X° and comes back up. // looks fine in a demo, dies in the real world final kneeAngle = angleBetween ( hip , knee , ankle ); if ( ! _down && kneeAngle < 100 ) _down = true ; if ( _down && kneeAngle > 160 ) { reps ++ ; _down = false ; } It demos beautifully. Then real users prop the phone on the floor, stand at an angle, and it falls apart. The trap: a phone camera gives you 2D pose. A "120° knee angle" flattens completely depending on where the camera sits — the same squat reads as 90° or 150° purely from perspective. Lifting to 3D via the model's z doesn't save you either; monocular z is noisy enough that the angle jitters across your threshold and double-counts. Naive attempt #2: a "body-line" gate Next idea: figure out which exercise you're doing so I can pick the right signal. Standing (squat) vs. horizontal (push-up) should be easy — just check if shoulder, hip and heel form a straight line, right? Wrong, again for the 2D reason. In a real push-up shot from the front-corner, shoulder–hip–heel are not collinear on the image plane — perspective bends them. I gated push-up counting on "body is a straight line" and it would just... stop counting mid-set. Nothing is more

2026-07-09 原文 →
AI 资讯

Why Serverpod? One Language for Your Entire Stack

Why this series I love writing clean architecture . Not because it looks nice in a diagram, but because it survives change — new requirements, new team members, and now, AI-assisted development , where you want boundaries an AI can respect and tests that catch it when it wanders. The problem in most Flutter stacks is the seam between app and backend. You write Dart on the client, then switch to a different language, a hand-written REST layer, DTOs that drift out of sync, and serialization bugs nobody notices until production. Serverpod removes that seam. You write Dart on the server too, and the client-server communication code is generated for you — type-safe, end to end. What is Serverpod? Serverpod is an open-source backend framework that lets you build the entire stack in Dart. Instead of context-switching between languages, your models, your API, and your database logic all live in one language. What you get out of the box: Endpoints — server methods your Flutter client calls directly. The communication code is generated, so there's no hand-written REST/JSON glue. An ORM — type-safe, statically analyzed database access with migrations and relationships. No raw SQL required. Code generation — define a model once; get serialization and client bindings on both sides automatically. Real-time data — streaming over WebSockets, managed for you. Auth — integrations for Google, Apple, and Firebase. The extras enterprises actually need — file uploads, task scheduling, caching, logging, and error monitoring. And on the "is this serious enough for production?" question: Serverpod says it's battle-tested in real-world apps and secured by over 5,000 automated tests, scaling from hobby projects to millions of users without code changes. That's exactly the property you want in an enterprise foundation. The architecture at a glance Here's how the pieces fit. A Serverpod project is generated as three packages: myapp_server → your backend: endpoints, models, business logic, DB my

2026-07-08 原文 →
AI 资讯

Can FlutterFlow Build a Better Dev.to App?

We have all been riding the massive vibe coding wave lately. It feels like pure magic to sit back, tell an AI assistant what to build, and watch a full application appear out of thin air. But if you have ever tried to take that exact same web workflow and deploy a smooth, native app onto an iPhone or Android, you know exactly where the frustration sets in. Are you a vibecoder who loves to build applications and you have built many websites? You have built and deployed many websites. Now you really want to make a mobile application that could disrupt the market and go really viral. Have you heard of FlutterFlow ? Have you tried using it? If the answer is no, then I will tell you about FlutterFlow and then you can decide whether you want to check it out and vibe code mobile applications. I will share the app that I created as well. What is FlutterFlow anyway? Have you ever tried building mobile applications and heard of Flutter and Dart? If you haven't, you should definitely check them out. When I was in college looking for a path to choose whether to pursue app development or web development. I explored both options. While exploring app development, I used and built applications using Flutter, an open-source framework created by Google, which uses a programming language called Dart. While Flutter itself is built by Google, FlutterFlow is an independent, visual low-code platform founded by ex-Google engineers. Today, many of us are familiar with AI vibe-coding tools like Cursor and Claude, which allow us to generate code for websites using conversational prompts. FlutterFlow, however, operates differently than vibe-coding: instead of writing code through chat prompts, it provides a visual, drag-and-drop canvas where you can build and design native mobile applications visually while it automatically generates clean Flutter code in the background. I recently had the opportunity to attend a workshop held by the FlutterFlow team and there, I was blown away by the magic of

2026-07-03 原文 →
AI 资讯

How to Implement Biometric Authentication in a Flutter App (The Right Way)

In today's world, security is no longer optional - it's expected. Whether it's a fintech app, a fitness tracker, or an internal company tool, users want fast and secure access without the hassle of remembering passwords. That's exactly where biometric authentication comes in. In this guide, we'll walk through how we implement biometric authentication in a Flutter app , the practical approach we follow in production, and the common mistakes developers often make (and how to avoid them). Why Biometric Authentication? Before jumping into implementation, let's quickly understand why it matters: Faster login experience (no typing passwords) More secure than traditional authentication Native support across Android & iOS Better user trust and retention What We Use in Flutter To implement biometric authentication, we rely on: local_auth package (official Flutter plugin) Native biometric APIs under the hood (Face ID, Touch ID, Fingerprint) Step 1: Add Dependency dependencies : local_auth : ^3.0.1 Then run: flutter pub get Step 2: Platform Setup ✅ Android Setup Inside android/app/src/main/AndroidManifest.xml : <uses-permission android:name= "android.permission.USE_BIOMETRIC" /> Also ensure: <uses-feature android:name= "android.hardware.fingerprint" android:required= "false" /> ✅ iOS Setup Inside ios/Runner/Info.plist : <key> NSFaceIDUsageDescription </key> <string> We use Face ID to authenticate you securely </string> ⚠️ Without this, Face ID will NOT work and your app may crash. Step 3: Implement Biometric Logic Here's how we structure it in production: import 'package:flutter/foundation.dart' ; import 'package:local_auth/local_auth.dart' ; class BiometricService { final LocalAuthentication _auth = LocalAuthentication (); /// Check if device supports biometrics Future < bool > isBiometricAvailable () async { try { final bool canCheckBiometrics = await _auth . canCheckBiometrics ; final bool isDeviceSupported = await _auth . isDeviceSupported (); return canCheckBiometrics &&

2026-07-01 原文 →
AI 资讯

Shipping one Flutter codebase to 6 platforms: what I learned building Tuneline

I spent the last several months solo-building Tuneline , a cross-platform media player, from a single Flutter codebase that ships native apps to macOS, Windows, Linux, Android, Google TV, and iOS . No Electron. Here is the stack and a few things that bit me. The stack Flutter 3.38 / Dart 3.10 — one codebase, six targets. media_kit for playback — libmpv on desktop, ExoPlayer on Android. Avoiding per-platform video plugins was the single biggest sanity win. Riverpod for state, Hive for local storage, Dio for HTTP. Node.js + Prisma backend for the cloud-sync layer, so your library, favorites, and settings replicate across devices. GoRouter with a single-route, tab-driven shell so the same layout reflows from a phone to a 10-foot TV UI. Things that bit me TV is its own design language. A 10-foot, focus-based UI is not a big phone. D-pad focus traversal, larger hit targets, and a separate Google TV store listing were all non-trivial. Per-platform video quirks. Desktop (libmpv) and mobile (ExoPlayer) disagree on enough edge cases that a shared abstraction over media_kit earned its keep. Sync is a distributed-systems problem in disguise. "Set up once, never rebuild it" sounds simple until two devices edit the same data offline. Keeping one canonical decoder for both the socket sync-down and the REST pull saved me from a whole class of drift bugs. One codebase is not one design. Window management on desktop, picture-in-picture per platform, and safe-area handling on mobile each needed platform-specific care even with a shared core. The product Tuneline is a bring-your-own-content player, like VLC — you supply your own playlists and it does not host anything. Every viewing feature is free on one device, and the only paid tier is cloud sync plus multi-device. No subscriptions. Site: https://tuneline.app — happy to answer any Flutter or cross-platform questions in the comments.

2026-06-21 原文 →