Как добавить список с виджетами в общие настройки Flutter?

Как мне сохранить данные списка виджетов на телефоне пользователей в автономном режиме без использования онлайн. Могу ли я использовать общие настройки для сохранения данных Список виджетов или есть ли какой-либо другой метод. Что на самом деле я делал, я хочу сохранить список и показать снова когда пользователь возвращается в мое приложение, но теперь приложение забывает данные с пустым списком.

class AlarmData extends ChangeNotifier {
    List<Alarm> _alarms = [
        Alarm(time:'04:05:06'),
        Alarm(time:'04:05:06'),
        Alarm(time:'04:05:06'),
    ];

    UnmodifiableListView<Alarm> get alarms{
        return UnmodifiableListView(_alarms);
    }

    void addAlarm(String newTaskTitle) {
        final task = Alarm(time: newTaskTitle);
        _alarms.add(task);
        notifyListeners();
    }

    void updateAlarm(Alarm task) {
        task.toggleDone();
        notifyListeners();
    }

    void deleteAlarm(Alarm task) {
        _alarms.remove(task);
        notifyListeners();
    }

    int get alarmCount {
        return alarms.length;
    }
}

Заранее спасибо Я новичок в разработке флаттера.


person Vikas Konaparthi    schedule 04.06.2020    source источник
comment
Общие настройки могут сохранять только список ‹String›, вы можете закодировать список в виде строки и сохранить его как файл jsok или как строку в общих настройках.   -  person EdwynZN    schedule 04.06.2020
comment
да, я спрашиваю, как я могу сохранить свой список с виджетами в локальной памяти пользователя   -  person Vikas Konaparthi    schedule 04.06.2020


Ответы (1)


Один из способов, который я мог придумать, - это кодировать их как Json и сохранять их как String либо в sharedPreferences, либо как файл в каталоге приложения (используя path_provider)

class Alarm{
  final String time;
  Alarm({this.time});

  @override
  toString(){
    return 'time: $time';
  }

  Map<String, dynamic> toJson() => {
    'time': this.time
  };

  factory Alarm.fromJson(Map<String, dynamic> alarm) => Alarm(
    time: alarm["time"],
  );

}

вашему классу Alarm нужны fromJson и toJson, чтобы правильно кодировать / декодировать. Я не знаю, есть ли у него другие параметры, но вы можете легко добавить их в конструктор и из / в Json.

//You could put this method inside AlarmData if you want to save it everytime you update your changeNotifier
Future<void> saveAlarms(List<Alarm> alarms) async{
  //Option 1 using SharedPreferences
  final SharedPreferences preferences = await SharedPreferences.getInstance();
  final String jsonEncoded = json.encode(alarms);
  await preferences.setString('MyAlarms', jsonEncoded);

  //Option 2 saving a json file in the documentsDirectory of the App
  final Directory appDocDir = await getApplicationDocumentsDirectory();
  final file = File('${appDocDir.path}/MyAlarms.json');
  await file.writeAsString(jsonEncoded);
}

Future<List<Alarm>> get retrieveAlarms async{
  //Option 1 using SharedPreferences
  final SharedPreferences preferences = await SharedPreferences.getInstance();
  final String myAlarms = await preferences.getString('MyAlarms');
  if(myAlarms?.isEmpty ?? true) return <Alarm>[]; //check for null or empty values

  final alarms = json.decode(myAlarms) as List;
  return List<Alarm>.from(alarms.map((x) => Alarm.fromJson(x)));

  //Option 2 saving a json file in the documentsDirectory of the App
  final Directory appDocDir = await getApplicationDocumentsDirectory();
  final readFile = File('${appDocDir.path}/MyAlarms.json');
  if(!(await readFile.exists())) return <Alarm>[]; //check if the file exists
  String jsonAlarms = await readFile.readAsString();
  final jResult = jsonDecode(jsonAlarms) as List;

  return List<Alarm>.from(jResult.map((x) => Alarm.fromJson(x)));

}

теперь вашим AlarmData нужен конструктор, в котором вы даете ему список сохраненных сигналов тревоги.

class AlarmData extends ChangeNotifier{
  List<Alarm> _alarms;

  AlarmData(this._alarms);
  ...
}

Вы либо выполняете future retrieveAlarms в основном, если вам это нужно в начале работы приложения, либо непосредственно перед AlarmData.

 Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();
  final myAlarms = await retrieveAlarms;
  runApp(const HomePage(myAlarms)); //if you want to use it as soon as possible
}

Если вы не против использования другого пакета, я бы рекомендовал использовать Hive, он позволяет хранить объекты и примитивные значения (как и sharedPreferences)

@HiveType(typeId: 0)
class Alarms extends HiveObject {

  @HiveField(0)
  String time;
}

Future<void> _initHive() async {
  final appDocumentDir  = await getApplicationDocumentsDirectory();
  Hive.init(appDocumentDir.path);
  Hive.registerAdapter<Alarms>(AlarmsAdapter()); //check the documentation of hive about how to generate this file
  await Hive.openBox<Alarms>('Alarm'); //a box where all your alarms are
}

Future<void> main() async {
    WidgetsFlutterBinding.ensureInitialized();
    await _initHive(); //if you want to use it as soon as possible
    runApp(const HomePage());
}

Я вижу, что ваш класс расширяет ChangeNotifier, с Hive у него есть опция Listenable из коробки, поэтому каждый раз, когда вы меняете (добавляете или удаляете будильник), он будет обновляться

ValueListenableProvider<Box<Alarm>>.value( //in case you're using provider package
     value: Hive.box<Alarm>('Alarm').listenable(),
),

OR

ValueListenableBuilder(
    valueListenable: Hive.box<Alarm>('Alarm').listenable(), 
    builder: (context) => ...
),
person EdwynZN    schedule 04.06.2020
comment
У вас есть идеи, как создать приложение-будильник на флаттере. - person Vikas Konaparthi; 06.06.2020
comment
Нет, на самом деле, я думаю, вам понадобятся знания java / kotlin в Android и Swift в iOS или пакет, который запускает код вне dart - person EdwynZN; 06.06.2020