AI 资讯
Mechanically Eliminating FutureBuilder & StreamBuilder: Universal Signal, Future, and Stream Adapters in BlocSignal
Making the Migration from In-View Asynchrony to Synchronous State Management Truly Mechanical After our recent discussions on why FutureBuilder and StreamBuilder are architectural anti-patterns when placed inside Flutter widget trees, I started thinking: how can we make it even easier—even completely mechanical—to convert from a FutureBuilder or StreamBuilder to a BlocSignalBuilder ? Every Flutter developer knows the history. Years ago, I recorded a video breaking down the hidden traps of placing asynchronous builders in UI views: Why you shouldn't put FutureBuilder in your build method . Even the original official Flutter video on FutureBuilder initially instantiated the network future directly inside the build() method, until I filed an issue to get it corrected (which is why the official Flutter YouTube video still proudly bears "Take 2" on its clapperboard!). The fundamental issue has never been that developers want bad architecture. The issue was friction . FutureBuilder was simply the path of least resistance. To do it "properly" in traditional state management, developers had to create an entire BLoC or Cubit, declare separate Event and State classes (or union types), write boilerplate event handlers, wire asynchronous repository methods, manage subscription lifecycles, and inject everything into the widget tree. With bloc_signals 1.1.0 , that friction disappears completely. We have introduced universal, symmetrical adapter extensions that allow any Dart Future , Stream , ReadonlySignal , or lifted primitive ( value.$ ) to adapt into a synchronous BlocSignalBase container with a single method call. 🧭 The Universal Dual-Track Mental Model When bridging asynchronous sources into synchronous state management, developers typically have one of two distinct intents: Raw Domain Values ( T ): You want raw domain objects (for example int , UserProfile , ThemeMode ) with zero wrapper ceremony, and you have an immediate default or fallback value for frame 0. Rich Asynch
AI 资讯
Why I built an app against fast swipe‑based social media: introducing SlowInk
Nowadays most social and pen‑pal apps are built around speed. Swipe left, swipe right, quick short messages, endless notifications. Platforms reward fast replies and surface‑level first impressions. We can chat with dozens of people every day, yet many of us still feel lonely. Connections are easy to start, but rarely grow deep. Even some existing pen‑pal apps gradually move toward swipe‑driven matching, focusing heavily on profile pictures instead of real thoughts. I wanted something different. What if we slow everything down? What if friendship starts from long, thoughtful letters rather than instant small‑talk? That is the original idea behind SlowInk . I am a solo indie developer building this application with Flutter. My goal was not to make another popular social product. I just wanted to solve a pain I felt myself: missing genuine, low‑pressure cross‑cultural communication. During development, I made several intentional product trade‑offs: No swipe matching mechanism. You will not judge people within one second by just looking at avatars. No real‑time instant chat. Communication happens through complete letters. You take your time writing, and others take their time replying. Reduce noisy notifications. There is no pressure to reply immediately. Focus on long‑form writing, for language exchange and sincere pen‑pal friendship. These choices brought technical challenges. Building a letter‑first social system is quite different from building typical instant‑messaging software. I spent a lot of time thinking about user privacy, spam prevention, and how to keep the atmosphere gentle for global users. Many features got cut in order to keep the core idea intact. SlowInk is still an early‑stage project. It is far from perfect. There are bugs to fix and features to polish. As a side‑project developer without large‑team support, every improvement moves forward little by little. If you feel tired of fast‑paced swipe‑based social media, or you enjoy writing and receiving
开源项目
Offline_SOS_System
Pub.dev Package: Link GitHub Repository: Link Imagine getting into a serious car crash in a remote...
开发者
I built flutter_auditor — a zero-config CLI tool to audit Flutter apps for permissions, dead assets, security risks, and package hygiene
Shipping a Flutter app without auditing native permissions, release keystores, or asset bloat? To help Flutter developers catch hidden production risks before App Store/Play Store review, I built flutter_auditor — an open-source, zero-config CLI health and security inspector for Flutter & Dart. In just one terminal command (dart run flutter_auditor), it scans your project for: 🔒 17+ Automated Audits: Hardcoded API secrets & exposed .jks keystores Missing iOS Info.plist privacy description strings Unused heavy assets & broken 2.0x/3.0x image variant paths Dangerous manifest flags (android:debuggable="true", allowed cleartext traffic) Unused & transitive package dependencies Give it a try locally on your project and let me know what audits you'd like to see next! 👇 pub.dev: https://pub.dev/packages/flutter_auditor GitHub: https://github.com/thakaredipali/flutter_auditor
科技前沿
‘Your Excel Skills Suck’: The Power Users Turning Spreadsheets Into a Spectator Sport
Data and finance professionals are competing in Excel obstacle courses—amassing huge followings and keeping the Microsoft program relevant.
AI 资讯
Viral Disneyland Content Creator Defends Her ‘Special Friendship’ With Peter Pan
Disney superfan Toni Kulusich has been accused of stalking her favorite character, sparking discourse about boundaries with park actors. She tells WIRED the backlash is unfair.
AI 资讯
Flutter Streaming UI: How the Typewriter Experience of AI Replies Is Built
The typewriter effect looks simple: characters appear one by one. But behind "skip animation", "no truncation", and "no performance regression" lies a whole set of engineering decisions. The implementation in this article is Flutter/Dart based, but the core semantic decisions — "skip ≠ abort" and "buffer and batch" — are framework-agnostic : Web's EventSource, and native/RN SSE clients, face the same choices. Prologue: a "skip typewriter" button that kept breaking In an AI narrative app (where the user influences an AI-driven interactive story by entering fate instructions), I built a "⏩ skip typewriter" button — users click it to see the full AI reply immediately instead of waiting for the text to appear character by character. The button went through three stages in the dev log: V1 : clicking does nothing — the callback fires, but the user experiences no change V2 : clicking truncates the content — the animation is gone, but the reply is incomplete too Final : clicking reveals the partial text immediately, while the LLM keeps generating the full reply in the background, which appears all at once when done Behind these three versions lie the three most common pitfalls in "streaming UI". This article breaks them down. 1. From SSE to screen: the streaming rendering pipeline Why the LLM "pops" text out The LLM's reply comes back in chunks via HTTP SSE (Server-Sent Events). A typical chunk looks like this: data: { "choices" :[{ "delta" :{ "content" : "Mephistopheles appears" }}]} data: { "choices" :[{ "delta" :{ "content" : "at the study door." }}]} data: [ DONE ] The interval between chunks is determined by the model's generation speed — tens of milliseconds when fast, possibly a full second when slow. That "character-by-character appearance" is what the user perceives as the typewriter animation. Why you can't update the UI on every chunk If you trigger a state update on every chunk, a reply of a few hundred characters can cause dozens or hundreds of UI rebuilds, whi
AI 资讯
Clean Architecture in Flutter with BLoC: A Practical Guide
Clean architecture in Flutter is the single biggest reason the production apps I ship stay maintainable after a year of feature churn. Over 4+ years building iOS and Android apps, I've watched "just put the logic in the widget" turn setState spaghetti into a codebase nobody wants to touch. This guide walks through how I actually split a Flutter app into domain , data , and presentation layers with BLoC — using one concrete feature so you can copy the structure into your own project today. I'll build a small "Todos" feature end to end: an entity, a use case, a repository with a DTO mapper, and a Cubit that drives the UI. The point isn't the todo list — it's the boundaries between layers and why each one earns its keep. Why clean architecture in Flutter pays off The core idea is the dependency rule : source-code dependencies point inward . The UI knows about the domain; the domain knows about nothing. Your business rules never import Flutter, Firebase, Dio, or Supabase. That inversion buys three things I care about on every project: Testability. Domain logic runs in plain Dart unit tests — no widget pump, no emulator, no network. Swappable infrastructure. Move from REST to GraphQL, or Firestore to a local SQLite cache, by rewriting one data-layer class. The domain and UI don't change. Parallel work. Once the domain contract exists, one person builds the API client while another builds the screen against a fake. Here's the layer breakdown I use, and what's allowed to live in each: Layer Knows about Contains Depends on Domain Nothing external Entities, repository interfaces , use cases Pure Dart only Data Domain + the outside world DTOs, mappers, repository implementations , data sources Domain Presentation Domain Blocs/Cubits, states, widgets Domain Notice the data and presentation layers both depend on domain, and domain depends on neither. That's the whole game. Folder structure that scales I organise by feature first, then by layer . A flat models/ , services/ , scr
AI 资讯
One-Shot UI Side Effects in BlocSignal: Snackbars, Dialogs, and Navigation Without State Pollution
Every Flutter developer has run into the Sticky State Dilemma . You build a login screen. When authentication fails, your state container emits an error. You catch it in your UI and show a SnackBar . Everything works—until the user rotates their phone, pulls down the notification shade, or types on the virtual keyboard. Suddenly, the widget tree rebuilds. The state container is still holding AuthErrorState("Invalid password") . The UI listener fires again. And a duplicate snackbar appears out of nowhere. In this article, we’ll explore why domain state machines struggle with transient UI events, how the classic BLoC community worked around this with package:bloc_presentation , and how BlocSignal lets you handle one-shot side effects cleanly with zero additional package dependencies . 1. The Root Problem: Persistent State vs. Ephemeral Actions State management in Flutter is designed to model persistent truth over time: Is the user logged in? AuthState.authenticated(user) Is data loading? TodoState.loading What is the cart total? $49.99 Persistent state answers: "What is the system's current condition?" In contrast, UI presentation actions are ephemeral pulses : Show a brief SnackBar toast. Pop up an alert confirmation dialog. Push a new route on the Navigator stack. Vibrate the haptic motor. These actions answer: "What just happened that requires a one-time reaction?" ┌────────────────────────────────────────────────────────┐ │ State vs. Effects │ ├────────────────────────────┬───────────────────────────┤ │ Persistent State │ Ephemeral Side-Effect │ ├────────────────────────────┼───────────────────────────┤ │ • Survived by UI rebuilds │ • Consumed once & gone │ │ • Represented in signals │ • Triggered by an event │ │ • Backed by equality diffs │ • Zero domain state footprint │ └────────────────────────────┴───────────────────────────┘ 2. The Legacy Workarounds (And Their Hidden Costs) Historically in package:bloc and package:flutter_bloc , developers used one of three
AI 资讯
Dogfooding BlocSignal on the Web: Building a 100K Ops/sec Reactive App with Jaspr and Dart 3.13
Building Pure Dart Web Apps Without Compromise When developers evaluate Dart for the web, they typically face a stark tradeoff: Flutter Web : Exceptional for canvas-driven applications, design systems, and cross-platform desktop/mobile parity—but heavy for content-first landing pages, docs, and fast-loading SEO sites. Jaspr Web : A lightweight, component-driven framework that compiles pure Dart to HTML and CSS with instant first paint and full search engine indexing. When we built the official documentation and showcase site for BlocSignal , we knew Jaspr was the perfect foundation. But like many engineers diving into a new UI paradigm, our initial implementation took a shortcut: we used raw StatefulComponent lifecycles and manual .subscribe() callbacks to wire up our state machines. It worked—but it wasn't idiomatic. In this behind-the-scenes case study, we walk through the process of dogfooding bloc_signals_jaspr across blocsignal.dev , replacing manual subscription glue with declarative consumer components, achieving 100,000 operations/sec in compiled JavaScript , and exploring the sheer developer ergonomics of Dart 3.13 primary constructors . The "Manual Subscription Trap": Why Raw .subscribe() Fails at Scale In classic Flutter or Jaspr development, when you create a state machine without framework-level consumer widgets, you might be tempted to subscribe inside initState() : // ❌ THE ANTI-PATTERN: Manual subscription glue in StatefulComponent class LiveVisualizerState extends State < LiveVisualizer > { late final LiveCounterBloc _bloc ; @override void initState () { super . initState (); _bloc = LiveCounterBloc (); // ⚠️ Flaw 1: Every state change triggers a full component setState _bloc . state . subscribe (( _ ) { if ( mounted ) setState (() {}); }); } @override void dispose () { // ⚠️ Flaw 2: Manual dispose tracking _bloc . close (); super . dispose (); } } While this appears harmless in a simple counter demo, it introduces three severe architectural flaws:
产品设计
Code Signing for Android/iOS
Every dev course teaches you to build the app. Almost none teach you how to actually ship it. I found that out the hard way on my first job — no signing, no publish, no exceptions. So I wrote the full setup, both platforms, both ways: → Android: keystore via CLI and Android Studio's GUI → iOS: manual signing (certs, App IDs, provisioning profiles) AND automatic signing → The exact steps before every archive/build Full walkthrough → https://medium.com/@smitp7502/from-keystore-to-app-store-understanding-code-signing-for-android-ios-30671b5fd2a2 flutter #android #ios #mobiledev
AI 资讯
Unit Testing in BlocSignal: The Practical Handbook
A Practical Guide to Faster, Deterministic Flutter & Dart Unit Testing If you’ve ever written unit tests for classic package:bloc applications using bloc_test , you know the drill: build your BLoC, dispatch an event in act , and assert state emissions in expect . Under the hood, classic BLoC processes state updates asynchronously via Dart microtask-queue Streams . While robust, testing asynchronous streams can introduce microtask timing headaches, race conditions, or the need to drain queues or use fakeAsync when testing complex side-effects. In BlocSignal , state updates propagate synchronously . Calling emit(newState) updates the underlying signal graph in the exact same call stack frame. This handbook is a practical, recipe-based guide to testing BlocSignal and CubitSignal applications using package:bloc_signals_test . Whether you’re coming from classic BLoC or brand new to Signals, this guide shows you how to test every scenario cleanly—and why it’s significantly easier than classic stream-based testing. 🤖 AI Assistant Tip : Working with an AI coding assistant (like Antigravity, Gemini CLI, or Cursor)? The official bloc-signals plugin includes a pre-built testing skill ( plugins/bloc-signals/skills/bloc-signals/ ) that automatically teaches your AI assistant these exact testing conventions, observer scoping rules, and declarative blocSignalTest patterns! 🛠️ Quick Reference: BLoC Streams vs. BlocSignal Testing Testing Task Classic BLoC ( package:bloc_test ) BlocSignal ( package:bloc_signals_test ) Why it’s easier in BlocSignal Execution Environment Often requires flutter test engine Pure dart test execution Blazing Speed : Business logic tests run in pure Dart CLI without booting Flutter UI engine. Simple State Assertions Requires async stream listener or blocTest Direct expect(cubit.state, 1) or blocSignalTest Synchronous : State updates on the next line of code without microtask delay. Failure Diagnostics Legacy Instance of 'CounterCubit' Built-in toString() :
开源项目
The ‘Manosphere’ Isn’t a Movement. It’s a Multibillion-Dollar Grievance Industry
Many young men are driven to resentment and are financially exploited as influencers sell them classes, pills, and the illusion of clout, a new report reveals.
科技前沿
Moderna's mRNA flu shot earns FDA approval after rollercoaster review
Moderna's new flu vaccine, mFLUSIVA, is approved for all adults ages 50 and up.
AI 资讯
A 500-Line Flutter Login Test Became One Promt
Lets start with a bit of back story. I am a full stack developer. Developer being the keyword here, not a QA developer. But in my current role, I was recently asked to come up with a testing suite for the web application and the Flutter app I was managing and maintaining. At that time, I didn’t have anything better to do and thought this would be a fun little project to work on for a couple of weeks. Boy o boy, I was wrong. People in QA are so opinionated. Everyone has their preferred framework, structure, naming convention, abstraction, folder structure and a very strong opinion about why your approach is wrong. Starting with the industry best practices I started by trying to follow the trends and best practices used in the industry. Page Object Models, reusable helpers, proper assertions and all the usual bits and bobs. For the web application, which was built with React, I chose Playwright. For the Flutter app, I went with integration_test . Sounded simple enough. The login test that took three hours The first test I tried to write was a simple login flow. Open the application Enter the username and password Press the login button Wait for the dashboard Easy, right? It took me ages. And by ages, I mean roughly three hours just to get the web test to pass reliably. The actual Playwright test ended up being around 300 lines once I included the boilerplate, setup, selectors, assertions, waits, Page Object Model structure and everything else needed around the actual journey. Then came the Flutter app. That one was worse. The app has its own custom way of starting different flavors, and both the web application and Flutter app are white-labelled products. That means there are a lot of variations to cover. Different branding, configurations, screens and sometimes slightly different user journeys. Before I could even test the login flow, I needed a pile of setup code just to launch the correct version of the app. The Flutter test eventually went beyond 500 lines, includ
AI 资讯
How I Made Features in a Large Flutter App Actually Removable
"Just delete the features you don't need" is the easiest thing in the world to write in a README, and the hardest to make true. I hit this building a Flutter app with six verticals in one codebase — marketplace, ride-hailing, car rentals, social feed, chat, wallet. Deleting one should have been simple. It wasn't, because every feature had tendrils: a route in the central route table a tab hardcoded in the app shell a button on the home screen a service registered in main() Remove the feature folder and you get a wall of compile errors from files that have nothing to do with it. Here's what actually worked. Make three things data instead of code 1. Routes Each feature exposes its own routes from its own folder: class WalletModule extends AppModule { const WalletModule (); @override String get id = > 'wallet' ; @override List < GetPage > get pages = > [ GetPage ( name: AppRoutes . wallet , page: () = > const WalletScreen ()), ]; } The app's route table becomes a composition: static final routes = < GetPage >[ .. . _centralRoutes , .. . ModuleRegistry . pages , ]; Adding or removing a feature stops being an edit to a shared file. It's one line in a registry. 2. Bottom-navigation tabs This one surprised me. My app shell imported the feed widget directly: // before — the always-present shell depends on an optional feature import '../feed/feed_tab.dart' ; The shell ships in every build. That import meant the social feature could never be removed. So a tab became a small data class that a feature contributes: class ShellTab { final String id ; final int order ; // core tabs use 10/30/40 final IconData icon ; final String labelKey ; final Widget Function () builder ; } Social contributes its tab at order 20, slotting between home and alerts without the shell knowing it exists. The shell merges its own tabs with ModuleRegistry.shellTabs and sorts. 3. Entry points Home screens linked to feature screens with Get.toNamed(...) . Named routes are already decoupled — no import nee
AI 资讯
Porting 16 BLoC & Signal Benchmark Apps to BlocSignal: Elevating Flutter UX & DX
🚀 Ported Example Benchmark Suite Live on blocsignal.dev ! If you’ve been evaluating BlocSignal —the monorepo package bridging the predictable event-driven BLoC architecture with Rody Davis's reactive signals v7 primitives—we’ve got something big to share. We just launched a dedicated Ported Example Suite containing 16 full-featured, runnable benchmark applications adapted directly from the official felangel/bloc (10 apps) and rodydavis/signals.dart (6 apps) example repositories. 🌐 Explore the Live Benchmark Suite : https://blocsignal.dev/ported-examples 💡 Why Port These Benchmark Apps? State management benchmarks are best understood through real-world applications. By porting these established examples 1-to-1, developers can compare BlocSignal side-by-side with original implementations to see concrete architectural benefits: 1. Synchronous Frame Updates (Better Test DX) In classic BLoC, state updates propagate asynchronously over microtask streams. In BlocSignal , emit() updates state synchronously on the exact same frame . This eliminates microtask queue latency, making widget building feel instant and allowing unit tests to assert expect(bloc.stateValue, ...) without pumpAndSettle or stream delays. 2. Reactive computed() Derivations (Zero Event Plumbing) In complex apps like Todos or Dynamic Forms , classic BLoC often requires dispatching intermediate filter events or wiring up CombineLatestStream . With BlocSignal , you declare late final ReadonlySignal<List<Todo>> filteredTodos = computed(...) right inside the constructor. When state changes, downstream signals derive updated values reactively and lazily. 3. Streamless Event Concurrency Transformers (Lower Overhead) Event concurrency transformers ( sequential() , droppable() , restartable() ) in BlocSignal are implemented as streamless higher-order functions using pure Dart Mutex locks. You get full request-cancellation and debouncing capabilities (e.g. in GitHub Search ) with zero RxStream memory allocations .
AI 资讯
Stacked Pull Requests: how I would split a Flutter feature into four reviewable layers
The problem is not the code I build Flutter apps. A normal feature touches four layers at once. Models and json parsing Repository and API client State management Screens and widgets When I ship that as one branch, the pull request is somewhere between 1,000 and 4,000 lines. And then one of two things happens. Either the reviewer opens 40 files, scrolls for ten minutes, and writes "looks good". That is not a review. That is a signature. Or the reviewer does the job properly, takes three days, and leaves a comment on the models file. Now every screen above it has to change. The writing was fast. The review was slow. That is the real bottleneck. The old workaround You already know it. Split the work into branches yourself. git checkout -b feat/booking-models git checkout -b feat/booking-repo # branched off models git checkout -b feat/booking-state # branched off repo git checkout -b feat/booking-ui # branched off state This works for about one day. Then a reviewer asks for a change in feat/booking-models , and you rebase three branches by hand. Then it happens again. Most people give up and go back to the giant branch. What stacked pull requests change On July 30 2026 GitHub put stacked pull requests into public preview. The idea is small. A stack is an ordered series of pull requests. Each pull request targets the one below it instead of targeting main . Only the bottom one targets main . PR #4 screens and widgets -> targets PR #3 PR #3 cubits and state -> targets PR #2 PR #2 repository and api -> targets PR #1 PR #1 models and parsing -> targets main Because each pull request only contains its own layer, opening PR #3 shows you the state management diff and nothing else. Not the models. Not the widgets. The Flutter example Say I am building a booking flow. Here is the same feature, sliced. PR 1 - models and json parsing. Around 190 lines. Targets main. class Booking { final String id ; final DateTime startsAt ; final BookingStatus status ; const Booking ({ required
AI 资讯
Article: Virtual Threads After JDK 24: What Changed for Production Java
JDK 24 removed the monitor-related carrier-thread pinning that stalled Netflix and similar teams on Java 21. What has replaced it on JDK 25 LTS is downstream-resource saturation: The bottleneck moved and now demands explicit bounding in application code. This article maps the failure modes that surface after virtual-thread adoption and gives a practical sequence backed by a public benchmark. By Sandeep Bharadwaj
科技前沿
Don’t Get Too Attached to Jimothy
Urban wildlife biologists say the stumpy raccoon seems to have adapted well to his environment and spinal condition—but his internet fame presents a new threat.