← Назад к вопросам

Расскажи про опыт работы с хранением данных

1.0 Junior🔥 51 комментариев
#Хранение данных

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI26 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Опыт работы с хранением данных в Flutter

Я имею обширный опыт работы с различными решениями для хранения данных в мобильных приложениях на Flutter. За годы работы использовал разные подходы в зависимости от требований проекта.

SharedPreferences — простые настройки и флаги

Это первое хранилище, с которым обычно начинают разработчики. Используется для:

  • Флагов пользователя (тема, язык, уведомления)
  • Токенов авторизации
  • Простых настроек приложения
import 'package:shared_preferences/shared_preferences.dart';

class PreferencesService {
  static const _keyTheme = 'theme_mode';
  static const _keyAuthToken = 'auth_token';
  
  static Future<void> setThemeMode(String mode) async {
    final prefs = await SharedPreferences.getInstance();
    await prefs.setString(_keyTheme, mode);
  }
  
  static Future<String?> getThemeMode() async {
    final prefs = await SharedPreferences.getInstance();
    return prefs.getString(_keyTheme);
  }
  
  static Future<void> clearAuthToken() async {
    final prefs = await SharedPreferences.getInstance();
    await prefs.remove(_keyAuthToken);
  }
}

SQLite — реляционные данные и кэширование

Для проектов, где нужна полноценная база данных. Использовал как sqflite (для простых случаев), так и ORM-фреймворки.

Зачем нужна:

  • Сложные связи между сущностями
  • Большой объём данных
  • Кэширование API ответов
  • Работа offline-first
import 'package:sqflite/sqflite.dart';
import 'package:path/path.dart';

class DatabaseService {
  static Database? _database;
  
  Future<Database> get database async {
    _database ??= await _initDatabase();
    return _database!;
  }
  
  Future<Database> _initDatabase() async {
    final databasesPath = await getDatabasesPath();
    final path = join(databasesPath, 'app.db');
    
    return await openDatabase(
      path,
      version: 1,
      onCreate: _createTables,
      onUpgrade: _upgradeTables,
    );
  }
  
  Future<void> _createTables(Database db, int version) async {
    await db.execute('''
      CREATE TABLE users (
        id INTEGER PRIMARY KEY,
        name TEXT NOT NULL,
        email TEXT UNIQUE NOT NULL,
        created_at DATETIME DEFAULT CURRENT_TIMESTAMP
      )
    ''');
    
    await db.execute('''
      CREATE TABLE posts (
        id INTEGER PRIMARY KEY,
        user_id INTEGER NOT NULL,
        title TEXT NOT NULL,
        content TEXT NOT NULL,
        FOREIGN KEY (user_id) REFERENCES users(id)
      )
    ''');
  }
  
  // Вставка пользователя
  Future<int> insertUser(Map<String, dynamic> user) async {
    final db = await database;
    return await db.insert('users', user);
  }
  
  // Получение всех постов пользователя
  Future<List<Map<String, dynamic>>> getPostsByUser(int userId) async {
    final db = await database;
    return await db.query(
      'posts',
      where: 'user_id = ?',
      whereArgs: [userId],
    );
  }
  
  // Обновление
  Future<int> updateUser(int id, Map<String, dynamic> user) async {
    final db = await database;
    return await db.update(
      'users',
      user,
      where: 'id = ?',
      whereArgs: [id],
    );
  }
}

Drift (бывший Moor) — типизированный ORM

В более новых проектах использую Drift для безопасности типов и автоматической генерации кода.

import 'package:drift/drift.dart';

part 'database.g.dart';

@DataClassName('User')
class Users extends Table {
  IntColumn get id => integer().autoIncrement()();
  TextColumn get name => text()();
  TextColumn get email => text().unique()();
  DateTimeColumn get createdAt => dateTime().withDefault(currentDateAndTime)();
}

@DriftDatabase(tables: [Users])
class AppDatabase extends _$AppDatabase {
  AppDatabase() : super(_openConnection());
  
  @override
  int get schemaVersion => 1;
  
  // Типизированные методы
  Future<List<User>> getAllUsers() => select(users).get();
  
  Future<void> insertUser(User user) => into(users).insert(user);
}

Hive — быстрое локальное хранилище

Для NoSQL подхода, когда нужна скорость и простота.

import 'package:hive/hive.dart';

@HiveType(typeId: 0)
class CachedResponse {
  @HiveField(0)
  final String url;
  
  @HiveField(1)
  final String data;
  
  @HiveField(2)
  final DateTime timestamp;
  
  CachedResponse({
    required this.url,
    required this.data,
    required this.timestamp,
  });
}

class CacheService {
  late Box<CachedResponse> _box;
  
  Future<void> init() async {
    _box = await Hive.openBox<CachedResponse>('cache');
  }
  
  void cache(String url, String data) {
    _box.put(url, CachedResponse(
      url: url,
      data: data,
      timestamp: DateTime.now(),
    ));
  }
  
  CachedResponse? getCache(String url) {
    return _box.get(url);
  }
}

Выбор подхода в реальных проектах

SharedPreferences

  • Флаги пользователя ✓
  • Простые настройки ✓
  • Небольшой объём данных ✓

SQLite / Drift

  • Сложные связи данных ✓
  • Офлайн-first стратегия ✓
  • Большой кэш от API ✓

Hive

  • Быстрое кэширование ✓
  • JSON документы ✓
  • Когда нужна скорость ✓

Лучшие практики

  1. Слой Repository: создавал абстракцию между UI и хранилищем
  2. Миграции: при изменении схемы БД проводил миграции
  3. Шифрование: для чувствительных данных использовал flutter_secure_storage
  4. Тестирование: мокировал хранилище для unit-тестов

Выбор решения зависит от требований проекта: простоты, производительности и сложности данных.

Расскажи про опыт работы с хранением данных | PrepBro