#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. Спасибо, ребята, вы сэкономили мне часы на устранении неполадок