Closed5

Flutterのデータ管理パッケージを使ってみる

薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

drift

準備コマンド

flutter create hello_drift
cd hello_drift
touch lib/table.dart
pubspec.yaml
dependencies:
  drift: ^2.3.0
  sqlite3_flutter_libs: ^0.5.0
  path_provider: ^2.0.0
  path: ^1.8.2

dev_dependencies:
  drift_dev: ^2.3.2
  build_runner: ^2.3.2

コード

table.dart
import 'dart:io';

import 'package:drift/drift.dart';
import 'package:path_provider/path_provider.dart';
import 'package:drift/native.dart';
import 'package:path/path.dart' as p;

part 'table.g.dart';

class Todos extends Table {
  IntColumn get id => integer().autoIncrement()();
  TextColumn get title => text().withLength(min: 6, max: 32)();
}

(tables: [Todos])
class MyDatabase extends _$MyDatabase {
  MyDatabase() : super(_openConnection());

  
  int get schemaVersion => 1;

  Stream<List<Todo>> watchTodos() {
    return select(todos).watch();
  }

  Future<void> addTodo(String title) async {
    await into(todos)
        .insert(TodosCompanion.insert(title: title));
  }

  Future<void> deleteTodo(int id) async {
    await (delete(todos)..where((t) => t.id.equals(id))).go();
  }
}

LazyDatabase _openConnection() {
  return LazyDatabase(() async {
    final dbFolder = await getApplicationDocumentsDirectory();
    final file = File(p.join(dbFolder.path, 'db.sqlite'));
    return NativeDatabase.createInBackground(file);
  });
}
lib/main.dart
import 'package:flutter/material.dart';
import 'package:hello_drift/table.dart';

Future<void> main() async {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  
  Widget build(BuildContext context) {
    return const MaterialApp(
      title: 'Flutter Demo',
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatelessWidget {
  const MyHomePage({super.key});

  
  Widget build(BuildContext context) {
    final database = MyDatabase();

    return Scaffold(
      appBar: AppBar(title: const Text("Todos")),
      body: StreamBuilder(
        stream: database.watchTodos(),
        builder: (context, snapshot) {
          if (snapshot.connectionState == ConnectionState.waiting) {
            return const Center(
              child: CircularProgressIndicator(),
            );
          } else {
            return ListView(
              children: [
                for (final todo in snapshot.data!)
                    ListTile(
                      onTap: () async {
                        await database.deleteTodo(todo.id);
                      },
                      title: Text(todo.title),
                    ),
              ],
            );
          }
        },
      ),
      floatingActionButton: FloatingActionButton.extended(
        onPressed: () async {
          await database.addTodo("Todo title");
        },
        label: const Text('Add'),
      ),
    );
  }
}

実行コマンド

flutter pub run build_runner build
flutter run

実行結果

メモ

勉強になりました

https://blog.flutteruniv.com/flutter-drift/

薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

shared_preferences

準備コマンド

flutter create hello_shared_preferences
cd hello_shared_preferences
flutter pub add shared_preferences

コード

hello_shared_preferences/lib/main.dart
import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  // This widget is the root of your application.
  
  Widget build(BuildContext context) {
    return const MaterialApp(
      title: 'Flutter Demo',
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key, required this.title});

  final String title;

  
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  static const counterKey = 'counter';

  late int _counter;
  late Future _getCounterFuture;

  
  void initState() {
    super.initState();
    _getCounterFuture = getCounter();
  }

  Future<void> getCounter() async {
    final prefs = await SharedPreferences.getInstance();
    _counter = prefs.getInt(counterKey) ?? 0;
  }

  Future<void> _incrementCounter() async {
    final counter = _counter + 1;
    final prefs = await SharedPreferences.getInstance();

    prefs.setInt(counterKey, counter);

    setState(() {
      _counter = counter;
    });
  }

  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: FutureBuilder(
        future: _getCounterFuture,
        builder: (context, snapshot) {
          if (snapshot.connectionState == ConnectionState.done) {
            return Center(
              child: Column(
                mainAxisAlignment: MainAxisAlignment.center,
                children: <Widget>[
                  const Text(
                    'You have pushed the button this many times:',
                  ),
                  Text(
                    '$_counter',
                    style: Theme.of(context).textTheme.headline4,
                  ),
                ],
              ),
            );
          } else {
            return const Center(
              child: CircularProgressIndicator(),
            );
          }
        },
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: const Icon(Icons.add),
      ),
    );
  }
}

実行コマンド

flutter run

実行結果

薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

flutter_secure_storage

準備コマンド

flutter create hello_secure_storage
cd hello_secure_storage
flutter pub add flutter_secure_storage

コード

hello_secure_storage/lib/main.dart
import 'package:flutter/material.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  
  Widget build(BuildContext context) {
    return const MaterialApp(
      title: 'Flutter Demo',
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatelessWidget {
  static const secretKey = 'secret';

  const MyHomePage({super.key});

  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text("AppBar Title"),
      ),
      body: FutureBuilder(
        future: writeAndReadSecret(),
        builder: (context, snapshot) {
          if (snapshot.connectionState == ConnectionState.done) {
            return Center(
              child: Text(
                snapshot.data!,
                style: Theme.of(context).textTheme.displayMedium,
              ),
            );
          } else {
            return const Center(
              child: CircularProgressIndicator(),
            );
          }
        },
      ),
    );
  }

  Future<String> writeAndReadSecret() async {
    const storage = FlutterSecureStorage();
    await storage.write(key: secretKey, value: 'SECRET');
    final value = await storage.read(key: secretKey);
    return value!;
  }
}

Androidの場合はcompileSdkVersionとminSdkVersionをそれぞれ33と18に設定する。

hello_secure_storage/android/app/build.gradle
android {
    compileSdkVersion 33
    defaultConfig {
        minSdkVersion 18
    }
}

実行コマンド

iOSまたはAndroid実機で実行する必要がある。

flutter run

実行結果

このスクラップは2023/01/10にクローズされました