"Stream Gemini Response in Flutter: Done Right"
"Waiting 8 seconds for a full Gemini reply kills the chat feel. Here's how to stream a Gemini response in Flutter token-by-token with generateContentStream: ChatSession memory, a typewriter UI that doesn't jank, working cancellation, and the error cases tutorials skip."
Your chat UI has a text field, a send button, and a prayer. The user taps send, and then… nothing. Three seconds. Five. Eight. The model is thinking, but your app looks dead. Most tutorials teach generateContent — fire, wait, render — and call it done. That's the demo path. In production, an 8-second blank screen reads as a frozen app. The fix is to stream a Gemini response in Flutter the way real chat apps do: tokens arrive as they're generated, the UI types them out live, and the user watches thinking happen. This guide covers the full pattern on firebase_ai 4.0 — generateContentStream , ChatSession memory, a typewriter UI, cancellation, and error handling. What you'll build By the end you'll have: A Firebase AI Logic client on firebase_ai 4.0 talking to gemini-2.5-flash A reusable service that turns generateContentStream into a clean Stream<String> of text chunks Streaming chat with memory via ChatSession , so the model remembers earlier turns A typewriter chat UI that appends tokens without rebuilding the whole message list A working stop button that actually cancels the in-flight stream Error handling for empty chunks, safety blocks, quota errors, and dead connections Set up firebase_ai 4.0 and create the model The old google_generative_ai package is deprecated — don't start new work on it. The current path is Firebase AI Logic through firebase_ai : # pubspec.yaml dependencies: flutter: sdk: flutter firebase_core: ^4.0.0 firebase_ai: ^4.0.0 // lib/main.dart import 'package:firebase_ai/firebase_ai.dart'; import 'package:firebase_core/firebase_core.dart'; import 'package:flutter/material.dart'; Future<void> main() async { WidgetsFlutterBinding.ensureInitialized(); await Firebase.initializeApp(); runApp(const…