Soy nuevo en Flutter y Dart. Hice una aplicación Todos simple con el paquete Provider y Consumer. Estoy tratando de implementar un proceso que usa el paquete flutter_secure_storage para leer y escribir los datos de la lista en el dispositivo. Pero no sé cómo implementarlo.

El widget Checkbox requiere un bool, mientras que secure_storage requiere el tipo de String. Por tanto, es necesario convertir ambos tipos. Esto también me confunde un poco.

El código está a continuación. Sería feliz si me pudiera dar algún consejo.

main.dart

// Todos app example

import 'package:consumer_samp/list_model.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      home: ChangeNotifierProvider<ListModel>(
        create: (context) => ListModel(),
        child: MyHomePage('Todos app example'),
      ),
    );
  }
}

class MyHomePage extends StatelessWidget {
  MyHomePage(this.title);

  final String title;

  final TextEditingController eCtrl = TextEditingController();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(title),
      ),
      body: SingleChildScrollView(
        child: Column(
          children: <Widget>[
            Container(
              padding: EdgeInsets.all(10),
              child: Row(
                children: <Widget>[
                  Expanded(
                    child: TextField(
                      decoration: InputDecoration(
                        border: InputBorder.none,
                        hintText: 'Enter your ToDo item',
                      ),
                      controller: eCtrl,
                    ),
                  ),
                  Consumer<ListModel>(
                    builder: (_, listModel, __) => FlatButton(
                      child: Text('Add'),
                      onPressed: () {
                        if (eCtrl.text != '') {
                          Map<String, dynamic> item = {
                            'value': false,
                            'text': eCtrl.text
                          };
                          listModel.addItem(item);
                          eCtrl.clear();
                        }
                      },
                    ),
                  ),
                ],
              ),
            ),
            Center(
              child: Consumer<ListModel>(builder: (_, listModel, __) {
                var items = listModel.getItems;
                return Column(
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: <Widget>[
                    Container(
                      height: 300,
                      child: ListView.builder(
                        itemCount: items.length,
                        itemBuilder: (BuildContext context, int idx) =>
                            Container(
                          padding: const EdgeInsets.all(5),
                          color: Colors.green,
                          child: Row(
                            children: <Widget>[
                              Checkbox(
                                  value: items[idx]['value'],
                                  onChanged: (val) {
                                    listModel.toggleValue(idx, val);
                                  }),
                              Text(
                                items[idx]['text'],
                                style: TextStyle(
                                    fontSize: 21, color: Colors.white),
                              ),
                            ],
                          ),
                        ),
                      ),
                    ),
                  ],
                );
              }),
            ),
          ],
        ),
      ),
    );
  }
}

list_model.dart

import 'package:flutter/cupertino.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart';

class ListModel with ChangeNotifier {
  List<Map<String, dynamic>> _items = [];

  List<Map<String, dynamic>> get getItems => _items;

  void addItem(Map<String, dynamic> item) {
    _items.add(item);
    notifyListeners();
  }

  void toggleValue(int idx, bool val) {
    _items[idx]['value'] = val;
    notifyListeners();
  }
}
1
cogane64 3 sep. 2020 a las 18:02

2 respuestas

La mejor respuesta

Puede copiar y pegar ejecutar el código completo a continuación
Puede usar la clase TodoItem y guardar / cargar con JSON String
La lógica de Provider para el almacenamiento seguro está en código completo, demasiado larga para describir los detalles
fragmento de código

List<TodoItem> todoItemFromJson(String str) =>
    List<TodoItem>.from(json.decode(str).map((x) => TodoItem.fromJson(x)));

String todoItemToJson(List<TodoItem> data) =>
    json.encode(List<dynamic>.from(data.map((x) => x.toJson())));

class TodoItem {
  TodoItem({
    this.item,
    this.checked,
  });

  String item;
  bool checked;

  factory TodoItem.fromJson(Map<String, dynamic> json) => TodoItem(
        item: json["item"],
        checked: json["checked"],
      );

  Map<String, dynamic> toJson() => {
        "item": item,
        "checked": checked,
      };
}

Demostración de trabajo

enter image description here

Código completo

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart';

import 'dart:convert';

List<TodoItem> todoItemFromJson(String str) =>
    List<TodoItem>.from(json.decode(str).map((x) => TodoItem.fromJson(x)));

String todoItemToJson(List<TodoItem> data) =>
    json.encode(List<dynamic>.from(data.map((x) => x.toJson())));

class TodoItem {
  TodoItem({
    this.item,
    this.checked,
  });

  String item;
  bool checked;

  factory TodoItem.fromJson(Map<String, dynamic> json) => TodoItem(
        item: json["item"],
        checked: json["checked"],
      );

  Map<String, dynamic> toJson() => {
        "item": item,
        "checked": checked,
      };
}

class ListModel with ChangeNotifier {
  FlutterSecureStorage _storage;

  List<TodoItem> _items = [];

  List<TodoItem> get getItems => _items;

  initilaize() async {
    print("initialize");
    String jsonString = await _storage.read(key: "todo");
    if (jsonString != null) {
      _items = todoItemFromJson(jsonString);
      notifyListeners();
    }
  }

  ListModel.init(FlutterSecureStorage storage) {
    print("init");
    _storage = storage;
    initilaize();
  }

  void update(FlutterSecureStorage storage) {
    print("update");
    _storage = storage;
  }

  void addItem(TodoItem item) {
    _items.add(item);
    notifyListeners();
  }

  void toggleValue(int idx, bool val) {
    _items[idx].checked = val;
    notifyListeners();
  }
}

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      home: MultiProvider(
        providers: [
          Provider<FlutterSecureStorage>(create: (_) => FlutterSecureStorage()),
          ChangeNotifierProxyProvider<FlutterSecureStorage, ListModel>(
            create: (_) {
              return ListModel.init(
                  Provider.of<FlutterSecureStorage>(_, listen: false));
            },
            update: (_, storage, listModel) => listModel..update(storage),
          ),
        ],
        child: MyHomePage('Todos app example'),
      ),
    );
  }
}

class MyHomePage extends StatelessWidget {
  MyHomePage(this.title);

  final String title;

  final TextEditingController eCtrl = TextEditingController();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(title),
        actions: <Widget>[
          Consumer2<ListModel, FlutterSecureStorage>(
              builder: (_, listModel, storage, __) => IconButton(
                    icon: Icon(Icons.save),
                    onPressed: () async {
                      await storage.write(
                          key: "todo", value: todoItemToJson(listModel._items));
                      print("save done");
                    },
                  ))
        ],
      ),
      body: SingleChildScrollView(
        child: Column(
          children: <Widget>[
            Container(
              padding: EdgeInsets.all(10),
              child: Row(
                children: <Widget>[
                  Expanded(
                    child: TextField(
                      decoration: InputDecoration(
                        border: InputBorder.none,
                        hintText: 'Enter your ToDo item',
                      ),
                      controller: eCtrl,
                    ),
                  ),
                  Consumer<ListModel>(
                    builder: (_, listModel, __) => FlatButton(
                      child: Text('Add'),
                      onPressed: () {
                        if (eCtrl.text != '') {
                          Map<String, dynamic> item = {
                            'value': false,
                            'text': eCtrl.text
                          };
                          listModel.addItem(
                              TodoItem(item: eCtrl.text, checked: false));
                          eCtrl.clear();
                        }
                      },
                    ),
                  ),
                ],
              ),
            ),
            Center(
              child: Consumer<ListModel>(builder: (_, listModel, __) {
                var items = listModel.getItems;
                return Column(
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: <Widget>[
                    Container(
                      height: 300,
                      child: ListView.builder(
                        itemCount: items.length,
                        itemBuilder: (BuildContext context, int idx) =>
                            Container(
                          padding: const EdgeInsets.all(5),
                          color: Colors.green,
                          child: Row(
                            children: <Widget>[
                              Checkbox(
                                  value: items[idx].checked,
                                  onChanged: (val) {
                                    listModel.toggleValue(idx, val);
                                  }),
                              Text(
                                items[idx].item,
                                style: TextStyle(
                                    fontSize: 21, color: Colors.white),
                              ),
                            ],
                          ),
                        ),
                      ),
                    ),
                  ],
                );
              }),
            ),
          ],
        ),
      ),
    );
  }
}
0
chunhunghan 4 sep. 2020 a las 09:29

Como se menciona en los archivos Léame del siguiente enlace

https://pub.dev/packages/flutter_secure_storage

El siguiente código crea una instancia del almacenamiento, y el siguiente código debe estar en un método async ya que devuelve un futuro.

final storage = new FlutterSecureStorage();

Y puede pasar la lista _items como un valor y puede establecer un nombre de clave

await storage.write(key: key, value: _items);

Y luego podría obtener ese valor usando el nombre de la clave (que se establece durante el almacenamiento)

List<Map<String, dynamic>> _value = await storage.read(key: key);

Y luego podría mapear el _value que obtiene del almacenamiento y puede almacenarlo en _items. Y luego podría hacer varias operaciones y consultas dentro de su aplicación ahora con todos los datos que tiene.

¡Haz una nota! No he probado este enfoque en mi base de código. Solo dije lo que pensaba. Intente esto en su código y coménteme por favor.

El siguiente código se ejecuta correctamente, use esto en el modelo, para almacenar datos:

Future<void> _storingData() async {
    final storage = new FlutterSecureStorage();

    for (int i = 0; i < _items.length; i++) {
        await storage
              .write(key: _items[i]['text'], value: "${_items[i]['value']}")
              .then((value) => print("success"));
    }
}

Para recuperar datos:

Future<void> retrivingData() async {
    final storage = new FlutterSecureStorage();
    Map<String, String> allValues = await storage.readAll();

    print(allValues);

    allValues.forEach((key, value) {
        bool val = bool.fromEnvironment(value, defaultValue: false);
        Map<String, dynamic> item = {'value': val, 'text': key};
        addItem(item);
    });
}

Y finalmente almacené todos los valores nuevamente en una lista.

Debería hacer algunos cambios en su código en main.dart de acuerdo con los métodos anteriores según su uso.

0
marc_s 4 sep. 2020 a las 10:15