Используя Flutter и Dart, это лучший способ достичь этого будущего? - PullRequest
0 голосов
/ 26 июня 2019

Я знаю, что есть другие способы достижения этого, но я хочу использовать Future через initState (), чтобы получить список с использованием SharedPreferences без использования await. Ниже показано, чего я хочу достичь, и это работает. Поскольку я никогда не использовал этот шаблон ранее, я просто не уверен, что это лучший способ (без использования await). Есть ли лучший способ без использования await?

import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';

class _MyHomePageState extends State<MyHomePage> {
  SharedPreferences _prefs;
  String _sMessage1;
  String _sMessage2;
  List<String> _lsCategories;

  @override
  void initState() {
    super.initState();
    Future<void> future = _initPreferences();
    future.then((_) {
      if (_prefs != null) {
        try {
          _lsCategories = _prefs.getStringList("categories") ?? [];
          debugPrint("Categories = $_lsCategories");
          _sMessage2 = "Categories loaded OK";
        } catch (vError) {
          _sMessage2 = ("Error loading categories = $vError");
        }
      }
      setState(() {});
    });
  }

  Future<void> _initPreferences() {
    return SharedPreferences.getInstance().then((prefs) {
      _prefs = prefs;
      _sMessage1 = "Preferences initialized OK";
    }).catchError((vError) {
      _sMessage1 = "Error initializing preferences = ${vError.toString()}";
      _sMessage2 = "Unable to load categories";
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            _createText(_sMessage1),
            SizedBox(height: 20),
            _createText(_sMessage2),
          ],
        ),
      ),
    );
  }
}

Text _createText(String sText) {
  return Text(sText == null ? "" : sText,
      style: TextStyle(
          color: Colors.red[500], fontWeight: FontWeight.bold, fontSize: 20));
}

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Future Test',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: "Flutter Future Test"),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);
  final String title;
  @override
  _MyHomePageState createState() => _MyHomePageState();
}


1 Ответ

0 голосов
/ 26 июня 2019

То, что вы сделали, прекрасно с точки зрения асинхронности. Однако это слишком многословно. Например, вам не нужно передавать экземпляр prefs через состояние.

Еще одним улучшением может быть проверка того, что виджет все еще монтируется после выполнения Future. (Если вы используете FutureBuilder, вам не нужно об этом беспокоиться.)

Проблема с вашим кодом в том, что вы устанавливаете переменные состояния вне setState(). Не гарантируется, что так будет хорошо работать, клянусь, когда-то я использовал старое состояние. Вы должны установить их в пределах setState()

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

  @override
  void initState() {
    super.initState();
    SharedPreferences.getInstance().then((prefs) {
      if(!mounted) return;
      setState(() {
        _prefs = prefs;
        _lsCategories = _prefs.getStringList("categories") ?? [];
        debugPrint("Categories = $_lsCategories");
        _sMessage2 = "Categories loaded OK";
      });
    }).catchError((vError) {
      setState(() {
        _sMessage2 = ("Error loading categories = $vError");
      });
    });
  }
  @override
  void initState() {
    super.initState();
    _initPreferences();
  }

  Future<void> _initPreferences() async {
    final prefs = await SharedPreferences.getInstance();
    if (!mounted) return;
    setState(() {
      try {
        _prefs = prefs;
        _lsCategories = _prefs.getStringList("categories") ?? [];
        debugPrint("Categories = $_lsCategories");
        _sMessage2 = "Categories loaded OK";
      } catch (vError) {
        _sMessage2 = ("Error loading categories = $vError");
      }
    });
  }
...