Gemini AI in Flutter: solved exercise with multi-turn chat and google_generative_ai
Gemini AI in Flutter: solved exercise with multi-turn chat
google_generative_ai is Google’s official package for consuming the Gemini API directly from Dart. It supports sending prompts, maintaining multi-turn conversation context, and configuring model behavior from the client — no backend required for non-sensitive use cases.
Problem statement
Build a Gemini chat app that:
- Configures
GenerativeModelwithgemini-1.5-flashandGenerationConfig. - Maintains conversation history with
ChatSession(multi-turn context). - Shows a loading indicator while the model generates a response.
- Handles API errors with clear messages.
- Protects the API key using
--dart-defineinstead of hardcoding it.
Dependencies
Configuration
1. Get an API key at Google AI Studio (free for development).
2. Run the app injecting the key as an environment variable to avoid writing it in code:
In production, use flavors or a secrets service (Google Secret Manager, AWS Secrets Manager, etc.).
Full solution
Key concepts
| API | Purpose |
|---|---|
GenerativeModel | Initializes the model with name, API key and config |
GenerationConfig | Controls temperature, max tokens, top-k, top-p |
systemInstruction | System instruction defining model behavior |
model.startChat() | Opens a ChatSession that maintains conversation history |
chat.sendMessage() | Sends a turn and returns GenerateContentResponse |
response.text | Generated text (quick access to the first candidate) |
Content.text() | Builds a text message for the model |
Content.system() | System message (only in systemInstruction) |
GenerativeAIException | Typed API error (quota, invalid key, safety) |
Common mistakes
- Empty or invalid API key: the model throws
GenerativeAIExceptionwith a clear message. Verify you passed--dart-define=GEMINI_API_KEY=...correctly. - Hardcoding the API key in source code: anyone who decompiles the APK can extract it. Use
--dart-definein development and a backend or secrets service in production. - Not managing the
_sendingflag: without a lock flag, the user can send multiple messages before receiving a response and desynchronize the history. - Not using
SelectableText: Gemini responses often include code;SelectableTextlets users copy the text, significantly improving the experience.
Practical application
This pattern is the foundation for onboarding assistants, content generators, semantic search features, and any functionality that enriches an app with generative AI. For production use cases with real users, Gemini calls should go through your own backend to control costs, add authentication, and log usage.
Recommended next exercises
- HTTP API consumption in Flutter: solved exercise
- GraphQL in Flutter: solved exercise
- WebSockets in Flutter: solved exercise
- All Flutter exercises
Guided practice and next step
- More Flutter exercises
- C exercises to strengthen fundamentals
- Programming in C in 100 Solved Exercises
- View on Amazon (included in Kindle Unlimited)
FAQ
Is Gemini 1.5 Flash free?
Yes, within Google AI Studio free plan limits: 15 RPM (requests per minute) and 1,500 RPD (requests per day). For production with higher traffic, a paid plan is required.
What is the difference between gemini-1.5-flash and gemini-1.5-pro?
Flash is optimized for speed and cost; Pro for complex reasoning and long contexts. For most chat apps, Flash is the right choice.
How do I add streaming responses so text appears word by word?
Use chat.sendMessageStream(Content.text(text)) which returns Stream<GenerateContentResponse>. Accumulate the text on each event and call setState on each chunk to simulate real-time typing.