Как дождаться начальной загрузки данных в flutter

#flutter #dart #flutter-layout

#flutter #dart #flutter-layout

Вопрос:

 // main.dart
void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MultiProvider(
      providers: [
        ChangeNotifierProvider<LoginProvider>(create: (_) => LoginProvider()),
      ],
      child: MaterialApp(
        debugShowCheckedModeBanner: false,
        routes: {
          '/' : (context) => LoginPage(),
          MainPage.routeName : (context) => MainPage(),
          RecipePage.routeName : (context) => RecipePage(),
          FoodPage.routeName : (context) => FoodPage(),
          LoginPage.routeName : (context) => LoginPage()
        },
      )
    );
  }
}
  
 // login_provider.dart
class LoginProvider with ChangeNotifier {
  static const String KEY_IS_LOGIN = "IS_LOGIN";
  static const String KEY_USER_ID = "USER_ID";

  User _me;
  bool _isLogin;

  LoginProvider() {
    setup();
  }

  void setup() async {
    SharedPreferences prefs = await SharedPreferences.getInstance();
    _isLogin = prefs.getBool(KEY_IS_LOGIN) ?? false;

    if(_isLogin) {
      String uid = prefs.getString(KEY_USER_ID);
      if(uid == null) {
        prefs.setBool(KEY_IS_LOGIN, false);
      } else {
        User user = await DBHelper.getUser(uid);
        
        if(user == null) {
          prefs.setBool(KEY_IS_LOGIN, false);
        } else {
          _me = user;
        }
      }
    }
  }

  bool get isLogin => _isLogin;

  void setLogin(String id) async {
    SharedPreferences prefs = await SharedPreferences.getInstance();
    prefs.setBool(KEY_IS_LOGIN, true);
    prefs.setString(KEY_USER_ID, id);
  }

  User get me => _me;

  set me(User value) {
    _me = value;
    notifyListeners();
  }
}
  
 // parts of DBHelper(db_helper.dart)
static Future<User> getUser(String uid) async {
  http.Response response = await http.get('http://$IP:3000/user/$uid');
  if(response.body == '{}') return null;
  return User.fromJsonString(response.body);
}
  

Я должен получать данные с сервера при запуске приложения.

В MultiProvider я вызвал LoginProvider конструктор.

И в LoginProvider конструкторе я вызвал setup функцию, которая загружает пользовательские данные с сервера, если идентификатор пользователя, который находится в SharedPreferences , действителен. (если идентификатор пользователя неверен, установите isLogin false.)

Итак, мое приложение должно дождаться полной загрузки пользовательских данных.

Кто-нибудь может мне помочь?

Спасибо.

Ответ №1:

У вас есть 2 варианта:

1 — Создайте заставку и вызывайте, ожидайте setup оттуда и перейдите на страницу входа в систему после этого.

2 — Вызов и ожидание setup со страницы входа. Пока метод не будет завершен, вам нужно показать какой-нибудь загрузочный виджет.

Вам нужно изменить setup на Future<void> , чтобы мы могли ожидать метод и вызывать его со страницы входа / заставки, а не из конструктора.

   Future<void> setup() async {
    SharedPreferences prefs = await SharedPreferences.getInstance();
    _isLogin = prefs.getBool(KEY_IS_LOGIN) ?? false;

    if(_isLogin) {
      String uid = prefs.getString(KEY_USER_ID);
      if(uid == null) {
        prefs.setBool(KEY_IS_LOGIN, false);
      } else {
        User user = await DBHelper.getUser(uid);
        
        if(user == null) {
          prefs.setBool(KEY_IS_LOGIN, false);
        } else {
          _me = user;
        }
      }
    }

  }
  

Либо параметры входа / заставки, вам нужен метод, который выглядит следующим образом:

 initState() {
super.initState();
// set initial loading widgets
loadDataFromModel();
}

void loadDataFromModel() async {
await Provider.of<LoginProvider>.setup();
setState(() {
// set your login widgets after the model fetched data
}) 
}
  

Или вы можете использовать альтернативный вариант FutureBuilder (прикрепленный setup в будущем к сборщику и обрабатывающий состояние соединения)

Комментарии:

1. Спасибо! Я решил это: await Provider.of<LoginProvider>(context, listen: false).setup();

2. Спасибо, ребята, вы сэкономили мне часы на устранении неполадок