On-Device AI in Flutter 2026: TensorFlow Lite Tutorial (Image Classifier App) đ¤
On-device AI: no cloud, no internetâ-âjust pure privacy and speed with TensorFlow Lite. Building Image Classifier App with Flutter x TensorFlow Lite.

Hello, I'm Samuel, also known as Tech With Sam.
I am passionate about learning and teaching programming, particularly Flutter and Dart at the moment. Please support me by subscribing to my newsletter. Thanks!
Subscribe for weekly tutorials and tips, or DM me to bring your app idea to life.
Questions? Join me on Discord: https://discord.gg/8X7dPYujqm For Business: techwithsam10@gmail.com
If youâve ever wanted AI in your Flutter app without Gemini API costs, this is it.
Hey guys! Itâs Samuel once again. Today, weâre going to be integrating something cool: On-device AI: no cloud, no internetâââjust pure privacy and speed with TensorFlow Lite. We will use TensorFlow Lite to build an image classifier that recognizes objects in real-time from your camera or gallery.
Why on-device in 2026? Cloud AI is great, but on-device wins for offline apps, privacy (no data sent), and battery life. Flutterâs ecosystem is mature. We have tflite_flutter that handles delegates beautifully now.
Weâll use MobileNet (quantized for mobile), download the .tflite model and labels.txt from TensorFlow Hub.
New project: flutter create ai_classifier.
Create a new assets folder in your project directory: assets/models, and download the mobilenet file and labels.text file and place it inside the assets/models folder.
Next, install dependencies in pubspec.yaml:
dependencies:
flutter_riverpod: ^3.2.0
google_fonts: ^7.1.0
camera: ^0.11.3
image_picker: ^1.2.1
tflite_flutter: ^0.12.1
path_provider: ^2.1.5
permission_handler: ^12.0.1
path: ^1.9.1
image: ^4.7.2
assets:
- assets/models/mobilenet_v1.tflite
- assets/models/labels.txt
TFLite helper: lib/providers/classifier_provider.dart
import âpackage:flutter_riverpod/flutter_riverpod.dartâ;
import â../services/tflite_service.dartâ;
final tfliteServiceProvider = Provider<TfliteService>((ref) {
return TfliteService();
});
final classifierInitializedProvider = FutureProvider<void>((ref) async {
final service = ref.watch(tfliteServiceProvider);
await service.init();
});
Tflite Service: lib/services/tflite_service.dart
import âpackage:tflite_flutter/tflite_flutter.dartâ;
import âpackage:image/image.dartâ as img;
class TfliteService {
late Interpreter _interpreter;
late List<String> _labels;
Future<void> loadModel() async {
_interpreter = await Interpreter.fromAsset(âmobilenet_v2.tfliteâ);
final labelsData = await rootBundle.loadString(âassets/labels.txtâ);
_labels = labelsData.split(â\nâ);
}
Future<List<Map<String, dynamic>>> predict(img.Image image) async {
// Preprocess: Resize to 224x224, normalize
final input = _preprocess(image);
final output = List.filled(1 * 1001, 0.0).reshape([1, 1001]);
_interpreter.run(input, output);
// Postprocess: Top 5 labels
final List<Map<String, dynamic>> results = [];
final outputList = output[0] as List<double>;
for (int i = 0; i < outputList.length; i++) {
results.add({âindexâ: i, âconfidenceâ: outputList[i]});
}
results.sort((a, b) => b[âconfidenceâ].compareTo(a[âconfidenceâ]));
return results.take(5).map((r) => {
âlabelâ: _labels[r[âindexâ] as int],
âconfidenceâ: (r[âconfidenceâ] as double * 100).toStringAsFixed(1),
}).toList();
}
// Full preprocess function (resize, normalize to [0,1] or [-1,1] per model)
// Use img package or custom
}
UI: Home screen with ImagePicker button.
Pick image â decode â run predict â display ListView of labels/confidence.
Add loading spinner + error handling.
File? _selectedImage;
List<Map<String, dynamic>>? _results;
bool _isCameraMode = false;
final ImagePicker _picker = ImagePicker();
Future<void> _pickImage(ImageSource source) async {
final XFile? image = await _picker.pickImage(source: source);
if (image != null) {
setState(() {
_selectedImage = File(image.path);
_results = null;
});
_classifyImage(_selectedImage!);
}
}
Future<void> _classifyImage(File file) async {
final service = ref.read(tfliteServiceProvider);
final results = await service.classifyImage(file);
setState(() {
_results = results;
});
}
Thatâs all! Demo on emulator/real device, pick a photo, see instant labels, and see how it works.

Full Source Code đâââShow some â¤ď¸ by starring â the repo and follow me đ!
https://github.com/techwithsam/vision_ai
I hope youâve learn something incredible. Press that follow button if youâre not following me yet. Also, make sure to subscribe to the newsletter so youâre notified when I publish a new article. Kindly press the clap button as many times as you want if you enjoy it, and feel free to ask a question.
đ Letâs Connect đ â Github | Twitter | Youtube | LinkedIn.
Join my Community đ¨âđťđ¨âđť on Discord.
Subscribe to my YouTube channel | and also to the Medium newsletter in the input box aboveđ or belowđ.
Happy Building! đĽ°đ¨âđť





