我尝试执行此操作,但这似乎并不好。
如果删除FutureBuilder
和CircularProgressIndicator
可以。
但是,最好在存储数据时花点时间。
有可能吗?
我的源代码:
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:serialtrip/config/theme.dart';
import 'package:serialtrip/pages/home.dart';
import 'package:serialtrip/pages/login.dart';
import 'package:serialtrip/providers/authProvider.dart';
main() {
runApp(
MultiProvider(
providers: [
ChangeNotifierProvider(
create: (_) => AuthProvider(),
),
],
child: MyApp(),
),
);
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Serialtrip',
debugShowCheckedModeBanner: false,
theme: defaultTheme,
home: context.watch<AuthProvider>().loggedInStatus == Status.LoggedIn
? Home()
: FutureBuilder(
future: context.read<AuthProvider>().autoLogin(),
builder: (ctx, authResultSnapshot) =>
authResultSnapshot.connectionState == ConnectionState.waiting ? CircularProgressIndicator() : Login(),
),
);
}
}
错误:
The following assertion was thrown building MyApp(dirty, dependencies: [_InheritedProviderScope<AuthProvider>]):
Tried to use `context.read<AuthProvider>` inside either a `build` method or the `update` callback of a provider.
This is unsafe to do so. Instead, consider using `context.watch<AuthProvider>`.
If you used `context.read` voluntarily as a performance optimisation, the solution
is instead to use `context.select`.
'package:provider/src/provider.dart':
Failed assertion: line 584 pos 9: 'debugIsInInheritedProviderCreate ||
(!debugDoingBuild && !debugIsInInheritedProviderUpdate)'
答案 0 :(得分:0)
试图在
context.read<AuthProvider>
中使用build
方法或提供者的update
回调
如果您阅读了文档,将会发现它不鼓励您使用context.read在build方法中使用Provider.of<AuthProvider>(context, listen: false).autoLogin();
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Serialtrip',
debugShowCheckedModeBanner: false,
theme: defaultTheme,
home: context.watch<AuthProvider>().loggedInStatus == Status.LoggedIn
? Home()
: FutureBuilder(
future: Provider.of<AuthProvider>(context, listen: false).autoLogin(),
builder: (ctx, authResultSnapshot) =>
authResultSnapshot.connectionState == ConnectionState.waiting ? CircularProgressIndicator() : Login(),
),
);
}
}
答案 1 :(得分:0)
我对FutureProvider的最后一次尝试,但不会自动登录:(
main.dart
Message.....Failure on QUSPTRUS call.
Message.....Operation not valid on system domain object.
Cause..... The requested operation is not valid on a system domain object. The object name is DMCREG in library *CURLIB.
Recovery.....You should use application programming interfaces to access system domain objects. An alternative is to create the object into the user domain. The QALWUSRDMN system value controls which libraries may contain user domain.objects.
Message.....Failure to obtain a key value for key CMN_JOBD.Failure code = 2. Please contact technical support for assistance.
Message..... Failure to initialize TCP Listener.TCP Listener encountered an error during initialization and can not continue execution. Please see previous message for more information about the error.
CDC Engine v.11.4.0
OS IBM i V7R3
Installer account : QSECOFR
authProvider.dart
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:serialtrip/config/theme.dart';
import 'package:serialtrip/pages/home.dart';
import 'package:serialtrip/pages/login.dart';
import 'package:serialtrip/pages/splash.dart';
import 'package:serialtrip/providers/authProvider.dart';
main() {
runApp(
MultiProvider(
providers: [
ChangeNotifierProvider(
create: (_) => AuthProvider(),
),
],
child: MyApp(),
),
);
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Serialtrip',
debugShowCheckedModeBanner: false,
theme: defaultTheme,
home: FutureProvider(
create: (_) => AuthProvider().autoLogin(),
initialData: Status.Authenticating,
child: _showScreen(context),
));
}
}
Widget _showScreen(BuildContext context) {
switch (context.watch<AuthProvider>().loggedInStatus) {
case Status.Authenticating:
return Splash();
case Status.LoggedIn:
return Home();
default:
return Login();
}
}
答案 2 :(得分:0)
第一个可能性
为了发挥autoLogin
功能的影响,您需要使用Consumer
Widget _showScreen(BuildContext context) {
return Consumer<Status>(
builder: (context, loginStatus, child) {
switch (loginStatus) {
case Status.Authenticating:
return Splash();
case Status.LoggedIn:
return Home();
default:
return Login();
}
}
);
}
如下更新您的autoLogin
函数。
Future<Status> autoLogin() async {
await new Future.delayed(const Duration(seconds: 2));
_loggedInStatus = Status.LoggedIn;
return _loggedInStatus;
}
第二种可能性(推荐)
如果您想连续地监听loggingInState的更改,则需要StreamProvider
,因为FutureProvier
仅监听一次更改。
在这种情况下,
MyApp Class
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Serialtrip',
debugShowCheckedModeBanner: false,
theme: defaultTheme,
home: StreamProvider(
create: (_) => AuthProvider().autoLogin(),
initialData: Status.Authenticating,
child: _showScreen(context),
));
}
}
AutoLogin Stream
您需要将AutoLogin
从将来更改为流式播放
Stream<Status> autoLogin() async* {
_loggedInStatus = Status.Authenticating;
yield _loggedInStatus;
await new Future.delayed(const Duration(seconds: 2));
_loggedInStatus = Status.LoggedIn;
yield _loggedInStatus;
}
Consumer
保持不变。
Widget _showScreen(BuildContext context) {
return Consumer<Status>(
builder: (context, loginStatus, child) {
switch (loginStatus) {
case Status.Authenticating:
return Splash();
case Status.LoggedIn:
return Home();
default:
return Login();
}
}
);
}
答案 3 :(得分:0)
好的,我找到了解决方案。我在应用程序首次启动时使用AuthProvider的构造函数来调用autoLogin()。
main.dart
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:serialtrip/config/theme.dart';
import 'package:serialtrip/pages/home.dart';
import 'package:serialtrip/pages/login.dart';
import 'package:serialtrip/pages/splash.dart';
import 'package:serialtrip/providers/authProvider.dart';
main() {
runApp(
MultiProvider(
providers: [
ChangeNotifierProvider(
create: (_) => AuthProvider(),
),
],
child: MyApp(),
),
);
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Serialtrip',
debugShowCheckedModeBanner: false,
theme: defaultTheme,
home: _showScreen(context),
);
}
}
Widget _showScreen(BuildContext context) {
switch (context.watch<AuthProvider>().loggedInStatus) {
case Status.Authenticating:
return Splash();
case Status.LoggedIn:
return Home();
default:
return Login();
}
}
authProvider.dart
import 'package:flutter/widgets.dart';
enum Status { NotLoggedIn, Authenticating, LoggedIn }
class AuthProvider with ChangeNotifier {
Status _loggedInStatus = Status.NotLoggedIn;
Status get loggedInStatus => _loggedInStatus;
/// Constructor
AuthProvider() {
_autoLogin();
}
/// Auto-login
Future<void> _autoLogin() async {
_loggedInStatus = Status.Authenticating;
notifyListeners();
print('autologin - waiting');
await new Future.delayed(const Duration(seconds: 5));
_loggedInStatus = Status.LoggedIn;
notifyListeners();
print('autologin - sucess');
}
/// Login
Future<void> login(String email, String password) async {
_loggedInStatus = Status.Authenticating;
notifyListeners();
print('login - waiting');
await new Future.delayed(const Duration(seconds: 2));
_loggedInStatus = Status.LoggedIn;
notifyListeners();
print('login - sucess');
}
/// Logout
Future<void> logout() async {
_loggedInStatus = Status.NotLoggedIn;
notifyListeners();
print('logout - sucess');
}
}