Pytania rekrutacyjne z Firebase 2026: Flutter Auth, Firestore i reguły bezpieczeństwa
Pytania rekrutacyjne z Firebase dla programistów Flutter z odpowiedziami w Darcie: strumienie stanu auth, Google Sign-In v7, CRUD i modelowanie w Firestore, reguły bezpieczeństwa, custom claims, transakcje i zmiany w FlutterFire 5.

Pytania rekrutacyjne z Firebase na stanowiska Flutter krążą wokół pięciu tematów: trzech strumieni stanu uwierzytelniania, modelowania danych w Firestore, reguł bezpieczeństwa, zapisów offline i modelu kosztów stojącego za każdym odczytem. Firebase pozostaje w 2026 roku domyślnym backendem aplikacji Flutter, a od października 2026 wtyczki FlutterFire są wydawane jako BoM 5.x (firebase_core 5.1.0, firebase_auth 7.0.1, cloud_firestore 7.1.0), z podniesionym na Androidzie minSdk do 24 i Firebase Apple SDK 13 pod spodem.
Aktualne wydanie FlutterFire to BoM 5.1.0: firebase_auth 7.0.1, cloud_firestore 7.1.0, firebase_core 5.1.0. Wersja główna 5.0.0 wymaga na Androidzie minSdk 24, opiera się na Firebase Apple SDK 13.0.0 i zmienia nazwy parametrów activate w App Check. Firestore Pipelines, dodane w cloud_firestore 6.3.0, zyskują nowe wyrażenia w każdym wydaniu.
Pytania rekrutacyjne z Firebase: o co pytają w 2026
Rekruterzy rzadko pytają o szczegóły API. Sprawdzają, czy kandydat rozumie, gdzie Firebase egzekwuje reguły, ile kosztuje każda operacja i co się dzieje po utracie sieci. Poniższa tabela zestawia powracające tematy z tym, co musi zawierać mocna odpowiedź. Każdy z nich jest omówiony szczegółowo niżej, w sekcji pytań rekrutacyjnych z Firebase dla programistów Flutter.
| Temat | Typowe pytanie | Co zawiera mocna odpowiedź |
|---|---|---|
| Strumienie auth | authStateChanges() vs idTokenChanges() vs userChanges() | Jakie zdarzenia emituje każdy z nich i który chroni nawigację |
| Bezpieczeństwo | Gdzie egzekwowana jest kontrola dostępu? | W regułach bezpieczeństwa na serwerze, nigdy w sprawdzeniach po stronie klienta; App Check to osobna warstwa |
| Role | Jak zaimplementować rolę administratora? | Custom claims ustawiane przez Admin SDK, odczytywane przez request.auth.token |
| Modelowanie danych | Zamodeluj aplikację czatu | Podkolekcje, zdenormalizowana ostatnia wiadomość, jeden dokument na wiadomość |
| Spójność | Transakcja czy zapis wsadowy? | Transakcja czyta, potem zapisuje i ponawia próbę; batch tylko zapisuje, atomowo |
| Offline | Co dzieje się z zapisem offline? | Lokalna pamięć podręczna, hasPendingWrites, synchronizacja po odzyskaniu połączenia |
| Koszty | Dlaczego ten ekran jest drogi? | Opłata za każdy odczytany dokument, listenery, paginacja kursorami |
| Porównanie | Firestore vs Realtime Database | Model zapytań, skalowanie, jednostka rozliczeniowa |
Konfiguracja Firebase w projekcie Flutter
Przed napisaniem jakiegokolwiek kodu Firebase projekt wymaga prawidłowej inicjalizacji. FlutterFire CLI automatyzuje rejestrację platformy i generuje pliki konfiguracyjne dla Android, iOS, web oraz macOS.
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/material.dart';
import 'firebase_options.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
// Initialize Firebase with platform-specific config
await Firebase.initializeApp(
options: DefaultFirebaseOptions.currentPlatform,
);
runApp(const MyApp());
}Plik firebase_options.dart jest generowany automatycznie po uruchomieniu flutterfire configure. Zawiera klucze API, identyfikatory projektu i identyfikatory specyficzne dla platformy, więc nic nie trzeba ręcznie kopiować z konsoli Firebase.
Uwierzytelnianie Firebase: Email, Google i uwierzytelnianie wielopoziomowe
Firebase Authentication obsługuje tożsamość użytkowników przy minimalnej ilości kodu szablonowego. Pakiet firebase_auth wspiera email/hasło, dostawców OAuth (Google, Apple, GitHub), weryfikację telefoniczną przez SMS oraz uwierzytelnianie wielopoziomowe (MFA), w tym TOTP na macOS od firebase_auth 6.1.0.
Rejestracja za pomocą adresu email i hasła
Najczęstszy przepływ rozpoczyna się od email/hasło. Metoda createUserWithEmailAndPassword zwraca obiekt UserCredential zawierający uwierzytelniony obiekt User.
import 'package:firebase_auth/firebase_auth.dart';
class AuthService {
final FirebaseAuth _auth = FirebaseAuth.instance;
// Register with email and password
Future<User?> register(String email, String password) async {
try {
final credential = await _auth.createUserWithEmailAndPassword(
email: email,
password: password,
);
return credential.user;
} on FirebaseAuthException catch (e) {
// Handle specific error codes
switch (e.code) {
case 'email-already-in-use':
throw Exception('This email is already registered');
case 'weak-password':
throw Exception('Password must be at least 6 characters');
default:
throw Exception('Registration failed: ${e.message}');
}
}
}
// Sign in with existing credentials
Future<User?> signIn(String email, String password) async {
final credential = await _auth.signInWithEmailAndPassword(
email: email,
password: password,
);
return credential.user;
}
// Reactive auth state stream
Stream<User?> get authStateChanges => _auth.authStateChanges();
}Strumień authStateChanges() to rekomendowany sposób śledzenia stanu logowania w całej aplikacji. Emituje bieżącego użytkownika User przy subskrypcji i reaguje ponownie przy każdym zdarzeniu logowania lub wylogowania.
Reguły haseł nie muszą już żyć wyłącznie w kliencie: API validatePassword (dostępne od firebase_auth 6.0.0) sprawdza hasło względem polityki skonfigurowanej w konsoli Firebase, która może wymagać minimalnej długości, wielkich i małych liter, cyfr oraz znaków specjalnych.
Integracja logowania przez Google
Dostawcy OAuth wymagają dodatkowego pakietu. Od google_sign_in 7.0 wtyczka jest singletonem dostępnym przez GoogleSignIn.instance, musi zostać zainicjalizowana dokładnie raz, a uwierzytelnianie jest oddzielone od autoryzacji. Wywołanie GoogleSignIn().signIn() ze starszych tutoriali już się nie kompiluje.
import 'package:firebase_auth/firebase_auth.dart';
import 'package:google_sign_in/google_sign_in.dart';
// Call once at startup, before any other GoogleSignIn method
Future<void> initGoogleSignIn() => GoogleSignIn.instance.initialize();
Future<UserCredential> signInWithGoogle() async {
try {
// Shows the native account picker; throws if the user cancels
final googleUser = await GoogleSignIn.instance.authenticate();
// Synchronous getter since v7: only the ID token is exposed here
final googleAuth = googleUser.authentication;
// Firebase only needs the ID token to create the credential
final credential = GoogleAuthProvider.credential(
idToken: googleAuth.idToken,
);
return FirebaseAuth.instance.signInWithCredential(credential);
} on GoogleSignInException catch (e) {
if (e.code == GoogleSignInExceptionCode.canceled) {
throw Exception('Sign-in cancelled');
}
rethrow;
}
}Ten wzorzec stosuje się do wszystkich dostawców OAuth: uzyskanie tokenu dostawcy, opakowanie go w credential Firebase, a następnie wywołanie signInWithCredential. Gdy aplikacja musi też wywoływać API Google (Drive, Calendar), token dostępu pochodzi teraz z osobnego kroku, authorizationClient.authorizeScopes, opisanego w przewodniku migracji google_sign_in.
Kandydat, który pisze GoogleSignIn().signIn() i odczytuje accessToken z authentication, cytuje API sprzed wersji 7.0. W v7 authenticate() zwraca konto, authentication zawiera tylko idToken, a tokeny dostępu do dodatkowych zakresów wymagają jawnego wywołania autoryzacji.
Operacje CRUD w Firestore i modelowanie danych
Cloud Firestore organizuje dane w kolekcje i dokumenty. W przeciwieństwie do baz SQL, Firestore nie wymaga schematu: każdy dokument może zawierać inne pola. Ta elastyczność dobrze pasuje do aplikacji Flutter, ale wymaga zdyscyplinowanego modelowania danych, aby uniknąć problemów z wydajnością.
Zapis i odczyt dokumentów
Operacje Firestore są proste dzięki pakietowi cloud_firestore. Każdy odczyt i zapis dotyczy konkretnej ścieżki dokumentu.
import 'package:cloud_firestore/cloud_firestore.dart';
class TaskService {
final _db = FirebaseFirestore.instance;
final String _collection = 'tasks';
// Create a new document with auto-generated ID
Future<String> createTask(String userId, String title) async {
final doc = await _db.collection(_collection).add({
'userId': userId,
'title': title,
'completed': false,
'createdAt': FieldValue.serverTimestamp(),
});
return doc.id;
}
// Read a single document by ID
Future<Map<String, dynamic>?> getTask(String taskId) async {
final snapshot = await _db.collection(_collection).doc(taskId).get();
return snapshot.data();
}
// Update specific fields without overwriting the entire document
Future<void> toggleComplete(String taskId, bool completed) async {
await _db.collection(_collection).doc(taskId).update({
'completed': completed,
'updatedAt': FieldValue.serverTimestamp(),
});
}
// Delete a document
Future<void> deleteTask(String taskId) async {
await _db.collection(_collection).doc(taskId).delete();
}
}FieldValue.serverTimestamp() zapewnia spójne znaczniki czasu na wszystkich urządzeniach, wykorzystując zegar serwera Firestore zamiast zegara klienta. Od cloud_firestore 7.1.0 do transformacji po stronie serwera dołączają FieldValue.minimum i FieldValue.maximum: zachowują mniejszą lub większą z wartości zapisanej i przychodzącej bez odczytu, co pasuje do liczników takich jak najlepszy wynik.
Strumienie czasu rzeczywistego z snapshots()
Firestore wyróżnia się synchronizacją w czasie rzeczywistym. Metoda snapshots() zwraca Stream, który emituje nowe dane za każdym razem, gdy bazowe dokumenty ulegną zmianie, bez konieczności odpytywania.
import 'package:cloud_firestore/cloud_firestore.dart';
class TaskStream {
final _db = FirebaseFirestore.instance;
// Stream all tasks for a specific user, ordered by creation date
Stream<List<Map<String, dynamic>>> userTasks(String userId) {
return _db
.collection('tasks')
.where('userId', isEqualTo: userId)
.orderBy('createdAt', descending: true)
.snapshots()
.map((snapshot) => snapshot.docs.map((doc) {
final data = doc.data();
data['id'] = doc.id; // Include document ID
return data;
}).toList());
}
}W widgecie Flutter ten strumień integruje się bezpośrednio z StreamBuilder, aby przebudowywać interfejs przy każdej zmianie w bazie danych. Firestore automatycznie zarządza połączeniami, buforowaniem i trwałością offline.
Gotowy na rozmowy o Flutter?
Ćwicz z naszymi interaktywnymi symulatorami, flashcards i testami technicznymi.
Reguły bezpieczeństwa Firestore dla aplikacji Flutter
Reguły bezpieczeństwa działają na serwerze Firestore i kontrolują dostęp do odczytu/zapisu na poziomie dokumentu. Bez odpowiednich reguł każdy uwierzytelniony użytkownik mógłby odczytać lub zmodyfikować dowolny dokument.
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
// Users can only access their own profile
match /users/{userId} {
allow read, update: if request.auth != null
&& request.auth.uid == userId;
allow create: if request.auth != null;
allow delete: if false; // Prevent self-deletion
}
// Tasks belong to the user who created them
match /tasks/{taskId} {
allow read, write: if request.auth != null
&& resource.data.userId == request.auth.uid;
allow create: if request.auth != null
&& request.resource.data.userId == request.auth.uid;
}
}
}Zmienna request.auth.uid zawiera identyfikator uwierzytelnionego użytkownika z Firebase Auth. Reguły odwołujące się do resource.data sprawdzają istniejące pola dokumentu, natomiast request.resource.data waliduje przychodzące dane zapisu.
Firestore domyślnie odmawia wszelkiego dostępu w trybie produkcyjnym. Każda kolekcja wymaga jawnych reguł. Częsty błąd w projektach Flutter: rozwijanie aplikacji z regułami trybu testowego (allow read, write: if true) i zapominanie o zabezpieczeniu przed wdrożeniem produkcyjnym.
Trwałość offline i strategia buforowania
Firestore domyślnie włącza trwałość offline na platformach mobilnych. Gdy urządzenie traci łączność, operacje odczytu zwracają dane z pamięci podręcznej, a operacje zapisu kolejkują się lokalnie do momentu wznowienia połączenia.
To zachowanie nie wymaga dodatkowego kodu we Flutterze: te same wywołania get() i snapshots() działają offline. Jednak w aplikacjach produkcyjnych istotne są dwie kwestie:
- Rozmiar pamięci podręcznej: Firestore buforuje wszystkie dokumenty, które klient odczytał. Dla aplikacji z dużą ilością danych warto skonfigurować
Settings(cacheSizeBytes: Settings.CACHE_SIZE_UNLIMITED)lub ustawić konkretny limit. - Wskaźnik oczekujących zapisów: Właściwość
SnapshotMetadata.hasPendingWritespozwala pokazać użytkownikom, kiedy lokalne zmiany nie zostały jeszcze zsynchronizowane z serwerem.
StreamBuilder<DocumentSnapshot>(
stream: FirebaseFirestore.instance
.collection('tasks')
.doc(taskId)
.snapshots(),
builder: (context, snapshot) {
if (!snapshot.hasData) return const CircularProgressIndicator();
final data = snapshot.data!;
final isPending = data.metadata.hasPendingWrites;
return Row(
children: [
Text(data['title']),
if (isPending) const Icon(Icons.cloud_upload, size: 16),
],
);
},
)Architektura produkcyjnej aplikacji Flutter z Firebase
Skalowalna architektura oddziela logikę Firebase od kodu UI. Wzorzec repozytorium zapewnia czystą warstwę abstrakcji, która upraszcza testowanie i przyszłe migracje backendu.
abstract class TaskRepository {
Future<String> create(String userId, String title);
Stream<List<Task>> watchAll(String userId);
Future<void> update(String id, Map<String, dynamic> fields);
Future<void> delete(String id);
}
// firebase_task_repository.dart
class FirebaseTaskRepository implements TaskRepository {
final _db = FirebaseFirestore.instance;
Future<String> create(String userId, String title) async {
final doc = await _db.collection('tasks').add({
'userId': userId,
'title': title,
'completed': false,
'createdAt': FieldValue.serverTimestamp(),
});
return doc.id;
}
Stream<List<Task>> watchAll(String userId) {
return _db
.collection('tasks')
.where('userId', isEqualTo: userId)
.orderBy('createdAt', descending: true)
.snapshots()
.map((s) => s.docs.map(Task.fromFirestore).toList());
}
// ... update and delete implementations
}Dzięki temu wzorcowi rozwiązania zarządzania stanem, takie jak Riverpod czy BLoC, konsumują interfejs repozytorium bez wiedzy o Firestore. Testy jednostkowe mogą podstawić mocka repozytorium zwracającego predefiniowane dane.
Migracja do FlutterFire 5: co przestaje działać
Październikowe wydanie główne z 2026 roku (BoM 5.0.0, firebase_auth 7.0.0, cloud_firestore 7.0.0, firebase_core 5.0.0) zmienia bardziej wymagania budowania niż API Darta. Punkty, na których pada build lub code review:
- Android
minSdk24: wtyczki opierają się na Firebase Android BoM 35. Projekt nadal ustawiony naminSdk21 lub 23 przestaje się kompilować. - Apple SDK 13: Firebase Apple SDK przechodzi na 13.0.0 ze Swift Package Manager (12.19.0 z CocoaPods), a pakiety Swift wymagają macOS 11.
- App Check: parametry
activatezmieniają nazwy naproviderWeb,providerAndroidiproviderApple. - Wycofania:
setIndexConfigurationFromJSONjest oznaczone jako deprecated wcloud_firestore7.0.0, afirebase_ml_model_downloadernie jest już publikowany. - Usunięte już w linii 6.x:
fetchSignInMethodsForEmail()iUser.updateEmail(). Kod, który przed logowaniem sprawdza, jakiego dostawcy używa dany adres email, trzeba przeprojektować, ponieważ ochrona przed enumeracją adresów email ukrywa tę informację.
Pełna lista zmian dla każdego pakietu znajduje się w informacjach o wydaniach FlutterFire i w changelogu cloud_firestore.
Pytania rekrutacyjne z Firebase dla programistów Flutter
Rozmowy kwalifikacyjne często sprawdzają zarówno zrozumienie koncepcyjne, jak i praktyczną implementację usług Firebase. Poniższe pytania regularnie pojawiają się na rozmowach z programistami Flutter w 2026 roku. Stronę samego frameworka obejmuje szerszy przewodnik po pytaniach rekrutacyjnych z Fluttera.
Czym różni się authStateChanges() od idTokenChanges() i userChanges()?
authStateChanges() reaguje wyłącznie na zdarzenia logowania i wylogowania. idTokenChanges() reaguje dodatkowo na odświeżenie tokenu ID (mniej więcej co 60 minut). userChanges() obejmuje wszystkie powyższe zdarzenia plus aktualizacje profilu, takie jak updateDisplayName(). Do większości zabezpieczeń nawigacyjnych wystarczający jest authStateChanges().
Co dzieje się, gdy zapis do Firestore następuje, gdy urządzenie jest offline?
Zapis jest przechowywany w lokalnej pamięci podręcznej i kolejce oczekujących zapisów. Listenery snapshots() natychmiast otrzymują zaktualizowane dane z metadata.hasPendingWrites == true. Po wznowieniu łączności Firestore automatycznie synchronizuje oczekujące zapisy, a wygrywa ostatni zapis, który dotrze do serwera.
Jak powinno wyglądać modelowanie danych Firestore dla aplikacji czatu?
Popularne podejście: kolekcja chats, gdzie każdy dokument zawiera metadane (uczestnicy, znacznik czasu ostatniej wiadomości) oraz podkolekcja messages pod każdym dokumentem czatu. Ta struktura umożliwia efektywne zapytania o listę czatów użytkownika przy jednoczesnym stronicowaniu wiadomości w każdej konwersacji. Denormalizacja ostatniej wiadomości do dokumentu nadrzędnego pozwala uniknąć odczytywania podkolekcji przy wyświetlaniu listy.
Dlaczego FieldValue.serverTimestamp() jest preferowane nad DateTime.now()?
DateTime.now() korzysta z zegara urządzenia, który może być niedokładny lub zmanipulowany. FieldValue.serverTimestamp() wykorzystuje zegar serwera Firestore, gwarantując spójne sortowanie na wszystkich klientach. Ma to znaczenie dla funkcji takich jak kolejność wiadomości, kanały aktywności i logi audytu.
Jak obsługiwane są zapytania złożone w Firestore i jakie są wymagania dotyczące indeksów?
Firestore wymaga indeksu złożonego dla zapytań łączących wiele pól z klauzulami where i orderBy. Indeksy jednopolowe są tworzone automatycznie, ale indeksy złożone muszą być zdefiniowane ręcznie w pliku firestore.indexes.json lub przez konsolę Firebase. Gdy zapytanie kończy się niepowodzeniem, Firestore loguje bezpośredni link do utworzenia brakującego indeksu.
Kiedy użyć transakcji zamiast zapisu wsadowego?
Transakcja jest potrzebna, gdy zapis zależy od danych odczytanych w tej samej operacji, na przykład zmniejszenie stanu magazynowego tylko wtedy, gdy jest większy od zera. SDK ponawia callback, jeśli odczytany dokument zmieni się przed zatwierdzeniem, więc callback nie może mieć efektów ubocznych. Zapis wsadowy (batch) wykonuje kilka zapisów atomowo bez żadnego odczytu, na przykład utworzenie dokumentu i aktualizację licznika w innym miejscu. Offline zachowują się inaczej: batch trafia do kolejki, transakcja bez połączenia kończy się błędem.
final db = FirebaseFirestore.instance;
// Transaction: read then write, retried on contention
await db.runTransaction((tx) async {
final ref = db.collection('products').doc(id);
final snap = await tx.get(ref);
final stock = snap.get('stock') as int;
if (stock <= 0) throw Exception('Out of stock');
tx.update(ref, {'stock': stock - 1});
});
// Batched write: atomic writes, no reads
final batch = db.batch();
batch.set(db.collection('orders').doc(), {'productId': id});
batch.update(db.collection('stats').doc('orders'), {
'count': FieldValue.increment(1),
});
await batch.commit();Jak zaimplementować rolę administratora w Firebase?
Za pomocą custom claims ustawianych z zaufanego środowiska przez Admin SDK, nigdy z klienta Flutter. Claim jest przenoszony w tokenie ID, więc reguły odczytują go jako request.auth.token.admin == true bez dodatkowego odczytu dokumentu. Dokumentacja custom claims ogranicza ładunek do 1000 bajtów, a klient widzi nowy claim dopiero po odświeżeniu tokenu, które wymusza currentUser.getIdToken(true).
Czym różnią się reguły bezpieczeństwa od App Check?
Reguły bezpieczeństwa decydują, czy dany użytkownik może odczytać lub zapisać dany dokument. App Check poświadcza, że żądanie pochodzi z oryginalnej aplikacji na prawdziwym urządzeniu, co blokuje skrypty wykorzystujące publiczny klucz API. Odpowiadają na różne pytania, dlatego aplikacja produkcyjna potrzebuje obu. Od FlutterFire 5 App Check aktywuje się parametrami providerAndroid, providerApple i providerWeb.
Dlaczego ekran oparty na Firestore może być drogi i jak działa paginacja?
Firestore nalicza opłaty za każdy odczyt, zapis i usunięcie dokumentu. Listener na nieograniczonej kolekcji przy pierwszym załadowaniu odczytuje każdy pasujący dokument, a potem wykonuje jeden odczyt na każdy zmieniony dokument. Paginacja używa kursorów zapytań zamiast offsetów: limit(20) dla pierwszej strony, potem startAfterDocument(lastDoc) dla kolejnej, więc każda strona kosztuje tylko tyle dokumentów, ile zwraca.
Firestore czy Realtime Database: co wybrać i dlaczego?
Firestore przechowuje dokumenty w kolekcjach, obsługuje zapytania złożone z indeksami i nalicza opłaty za operacje. Realtime Database przechowuje jedno drzewo JSON, oferuje płytkie zapytania po jednym kluczu potomnym i nalicza opłaty głównie za transfer i przechowywanie, co pasuje do małych, bardzo częstych aktualizacji, takich jak wskaźniki obecności. Większość nowych aplikacji Flutter zaczyna od Firestore i dodaje Realtime Database tylko do obsługi obecności.
Więcej materiałów do przygotowania do rozmów kwalifikacyjnych z Flutter i Firebase dostępnych jest w interaktywnych modułach ćwiczeniowych, które obejmują te zagadnienia w formie interaktywnych quizów i zadań na czas.
Zacznij ćwiczyć!
Sprawdź swoją wiedzę z naszymi symulatorami rozmów i testami technicznymi.
Źródła
- Informacje o wydaniach Firebase dla Fluttera: zawartość BoM 5.0.0 i 5.1.0, minSdk 24, zmiana nazw parametrów App Check
- Changelog cloud_firestore: Pipelines w 6.3.0,
FieldValue.minimum/maximumi odległość wfindNearestw 7.1.0 - Changelog firebase_auth:
validatePasswordw 6.0.0, TOTP na macOS w 6.1.0, usunięciefetchSignInMethodsForEmail - Przewodnik migracji google_sign_in: singleton,
initialize,authenticate, oddzielna autoryzacja w 7.0 - Custom claims w Firebase: limit 1000 bajtów i odświeżanie tokenu
Najważniejsze wnioski o Flutter i Firebase przed rozmową rekrutacyjną
- FlutterFire BoM 5.1.0 zawiera
firebase_auth7.0.1 icloud_firestore7.1.0 oraz wymaga na AndroidzieminSdk24 google_sign_in7 zastępujeGoogleSignIn().signIn()wywołaniemGoogleSignIn.instance.initialize(), a potemauthenticate(), a Firebase potrzebuje tylkoidTokenauthStateChanges()dostarcza reaktywny strumień do zarządzania stanem logowania w całej aplikacji bez ręcznych sprawdzeń- Synchronizacja w czasie rzeczywistym przez
snapshots()eliminuje odpytywanie i współpracuje bezpośrednio zeStreamBuilder, automatycznie aktualizując interfejs - Reguły bezpieczeństwa są obowiązkowe na produkcji:
request.auth.uidnależy zawsze porównywać z polami własności dokumentu, a role realizować przez custom claims - Transakcja czyta, potem zapisuje i ponawia próbę, zapis wsadowy tylko zapisuje; paginacja używa kursorów, bo każdy odczytany dokument jest płatny
- Trwałość offline działa na urządzeniach mobilnych bez dodatkowego kodu;
hasPendingWritespozwala informować użytkowników o stanie synchronizacji - Wzorzec repozytorium oddziela Firebase od logiki biznesowej, co ułatwia testowanie i przyszłe migracje
Znajdziesz błąd w Flutter?
Prawdziwy fragment kodu, ukryty błąd, jedna próba dziennie. Bez konta, żeby spróbować.

Autor:
Anthony Fillion-MailletZałożyciel SharpSkill
Programista fullstack od ponad 10 lat. Prowadzi SharpSkill i odpowiada za wszystko, co się tu ukazuje.
Zaktualizowano 9 listopada 2026
Tagi
Udostępnij
Powiązane artykuły

Zarządzanie Stanem w Flutter: Riverpod vs BLoC - Kompletny Przewodnik Porównawczy
Szczegółowe porównanie Riverpod 3.x i BLoC 9.x do zarządzania stanem we Flutterze. Architektura, automatyczne ponawianie, testowalność i przypadki użycia, by wybrać najlepsze rozwiązanie.

20 pytan rekrutacyjnych z Flutter dla programistow mobilnych
Przygotowanie do rozmowy kwalifikacyjnej z Flutter: 20 najczesciej zadawanych pytan. Widgety, zarzadzanie stanem, Dart, architektura i najlepsze praktyki z przykladami kodu.

Flutter: Budowanie pierwszej aplikacji wieloplatformowej
Kompletny przewodnik po tworzeniu wieloplatformowej aplikacji mobilnej z Flutter i Dart. Widgety, zarzadzanie stanem, nawigacja i dobre praktyki dla poczatkujacych.