所以我一直在尝试调用用户数据一段时间,实际上我遇到了一些障碍。首先,我尝试使用 Stream,但后来决定进入 Future,因为 Stream 无法正常工作,现在我得到了这个错误。
Notifying id token listeners about user ( jIjnj3FjR0fg7EWI5RxK3J2SYGH3 ).
D/FirebaseAuth(16764): Notifying auth state listeners about user ( jIjnj3FjR0fg7EWI5RxK3J2SYGH3 ).
E/flutter (16764): [ERROR:flutter/lib/ui/ui_dart_state.cc(166)] Unhandled Exception: setState() called after dispose(): _LogInState#a1c31(lifecycle state: defunct, not mounted)
E/flutter (16764): This error happens if you call setState() on a State object for a widget that no longer appears in the widget tree (e.g., whose parent widget no longer includes the widget in its build). This error can occur when code calls setState() from a timer or an animation callback.
E/flutter (16764): The preferred solution is to cancel the timer or stop listening to the animation in the dispose() callback. Another solution is to check the "mounted" property of this object before calling setState() to ensure the object is still in the tree.
E/flutter (16764): This error might indicate a memory leak if setState() is being called because another object is retaining a reference to this State object after it has been removed from the tree. To avoid memory leaks, consider breaking the reference to this object during dispose().
E/flutter (16764): #0 State.setState.<anonymous closure> (package:flutter/src/widgets/framework.dart:1204:9)
E/flutter (16764): #1 State.setState (package:flutter/src/widgets/framework.dart:1239:6)
E/flutter (16764): #2 _LogInState.build.<anonymous closure> (package:SAT/screens/authentication/logIn.dart:116:33)
E/flutter (16764): <asynchronous suspension>
E/flutter (16764): #3 _LogInState.build.<anonymous closure> (package:SAT/screens/authentication/logIn.dart)
E/flutter (16764): #4 _InkResponseState._handleTap (package:flutter/src/material/ink_well.dart:992:19)
E/flutter (16764): #5 _InkResponseState.build.<anonymous closure> (package:flutter/src/material/ink_well.dart:1098:38)
E/flutter (16764): #6 GestureRecognizer.invokeCallback (package:flutter/src/gestures/recognizer.dart:184:24)
E/flutter (16764): #7 TapGestureRecognizer.handleTapUp (package:flutter/src/gestures/tap.dart:524:11)
E/flutter (16764): #8 BaseTapGestureRecognizer._checkUp (package:flutter/src/gestures/tap.dart:284:5)
E/flutter (16764): #9 BaseTapGestureRecognizer.handlePrimaryPointer (package:flutter/src/gestures/tap.dart:219:7)
E/flutter (16764): #10 PrimaryPointerGestureRecognizer.handleEvent (package:flutter/src/gestures/recognizer.dart:477:9)
E/flutter (16764): #11 PointerRouter._dispatch (package:flutter/src/gestures/pointer_router.dart:78:12)
E/flutter (16764): #12 PointerRouter._dispatchEventToRoutes.<anonymous closure> (package:flutter/src/gestures/pointer_router.dart:124:9)
E/flutter (16764): #13 _LinkedHashMapMixin.forEach (dart:collection-patch/compact_hash.dart:377:8)
E/flutter (16764): #14 PointerRouter._dispatchEventToRoutes (package:flutter/src/gestures/pointer_router.dart:122:18)
E/flutter (16764): #15 PointerRouter.route (package:flutter/src/gestures/pointer_router.dart:108:7)
E/flutter (16764): #16 GestureBinding.handleEvent (package:flutter/src/gestures/binding.dart:220:19)
E/flutter (16764): #17 GestureBinding.dispatchEvent (package:flutter/src/gestures/binding.dart:200:22)
E/flutter (16764): #18 GestureBinding._handlePointerEvent (package:flutter/src/gestures/binding.dart:158:7)
E/flutter (16764): #19 GestureBinding._flushPointerEventQueue (package:flutter/src/gestures/binding.dart:104:7)
E/flutter (16764): #20 GestureBinding._handlePointerDataPacket (package:flutter/src/gestures/binding.dart:88:7)
E/flutter (16764): #21 _rootRunUnary (dart:async/zone.dart:1206:13)
E/flutter (16764): #22 _CustomZone.runUnary (dart:async/zone.dart:1100:19)
E/flutter (16764): #23 _CustomZone.runUnaryGuarded (dart:async/zone.dart:1005:7)
E/flutter (16764): #24 _invoke1 (dart:ui/hooks.dart:267:10)
E/flutter (16764): #25 _dispatchPointerDataPacket (dart:ui/hooks.dart:176:5)
E/flutter (16764):
W/DynamiteModule(16764): Local module descriptor class for providerinstaller not found.
I/DynamiteModule(16764): Considering local module providerinstaller:0 and remote module providerinstaller:0
W/ProviderInstaller(16764): Failed to load providerinstaller module: No acceptable module found. Local version is 0 and remote version is 0.
I/zygote (16764): The ClassLoaderContext is a special shared library.
I/zygote (16764): The ClassLoaderContext is a special shared library.
V/NativeCrypto(16764): Registering com/google/android/gms/org/conscrypt/NativeCrypto's 286 native methods...
D/NetworkSecurityConfig(16764): No Network Security Config specified, using platform default
I/ProviderInstaller(16764): Installed default security provider GmsCore_OpenSSL
I/zygote (16764): Do partial code cache collection, code=122KB, data=80KB
I/zygote (16764): After code cache collection, code=122KB, data=80KB
I/zygote (16764): Increasing code cache capacity to 512KB
这一切都从 main.dart 开始,它看起来像这样并为用户生成一个流。
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
import 'package:MyApp/screens/authentication/handler.dart';
import 'package:MyApp/services/auth.dart';
import 'package:MyApp/services/geolocator.dart';
import 'package:MyApp/models/user.dart';
import 'package:flutter/services.dart';
import 'package:provider/provider.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
final locatorService = GeolocatorService();
@override
Widget build(BuildContext context) {
SystemChrome.setPreferredOrientations([
DeviceOrientation.portraitUp,
]);
return MultiProvider(
providers: [
StreamProvider<User>.value(
value: AuthService().user,
),
FutureProvider(create: (context) => locatorService.getLocation)
],
child: MaterialApp(
debugShowCheckedModeBanner: false,
theme: ThemeData(
primarySwatch: Colors.yellow,
accentColor: Colors.black,
canvasColor: Colors.black,
),
initialRoute: "/",
routes: {
"/": (ctx) => Handler(),
},
),
);
}
}
然后通过执行此操作的处理程序:
import 'package:MyApp/models/user.dart';
import 'package:flutter/material.dart';
import 'package:MyApp/screens/clientSide/home.dart';
import 'package:provider/provider.dart';
import 'package:MyApp/screens/authentication/authenticate.dart';
class Handler extends StatelessWidget {
@override
Widget build(BuildContext context) {
final user = Provider.of<User>(context);
// return either the Home or Authenticate widget
if (user == null) {
return Authenticate();
} else {
return Home();
}
}
}
现在,在这样做之后,它会侦听一个不为 null 的用户,这仅在调用 register 或 signIn 函数时由我的 auth.dart 服务更改。
import 'package:MyApp/services/database.dart';
import 'package:MyApp/models/user.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
class AuthService {
final FirebaseAuth _auth = FirebaseAuth.instance;
// create user obj based on firebase user
User _userFromFirebaseUser(FirebaseUser user) {
return user != null ? User(uid: user.uid) : null;
}
// auth change user stream
Stream<User> get user {
return _auth.onAuthStateChanged.map(_userFromFirebaseUser);
}
// sign in with email and password
Future signInWithEmailAndPassword(String email, String password) async {
try {
AuthResult result = await _auth.signInWithEmailAndPassword(
email: email, password: password);
FirebaseUser user = result.user;
return user;
} catch (error) {
print(error.toString());
return null;
}
}
// register with email and password
Future registerWithEmailAndPassword(String email, String password,
Timestamp birthdate, String firstName, String lastName) async {
try {
AuthResult result = await _auth.createUserWithEmailAndPassword(
email: email, password: password);
FirebaseUser user = result.user;
// Create User in Collection
await DatabaseService(uid: user.uid)
.createUserData(firstName, lastName, email, birthdate);
return _userFromFirebaseUser(user);
} catch (error) {
print(error.toString());
return null;
}
}
// sign out
Future signOut() async {
try {
return await _auth.signOut();
} catch (error) {
print(error.toString());
return null;
}
}
}
我的崩溃并需要修复的代码从 home.dart 开始,如下所示:
import 'package:MyApp/models/user.dart';
import 'package:MyApp/services/auth.dart';
import 'package:MyApp/services/database.dart';
import 'package:MyApp/services/language.dart';
import 'package:MyApp/services/time.dart';
import 'package:MyApp/widgets/shared/loading.dart';
import 'package:flutter/material.dart';
import 'package:geolocator/geolocator.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
import 'package:provider/provider.dart';
import 'package:flutter/services.dart' show rootBundle;
class Home extends StatefulWidget {
@override
_HomeState createState() => _HomeState();
}
class _HomeState extends State<Home> {
final AuthService _auth = AuthService();
GoogleMapController mapController;
String _mapStyle;
@override
Widget build(BuildContext context) {
final currentPosition = Provider.of<Position>(context);
var activeLanguage = Provider.of<Language>(context).getLanguage;
var mapChange = Provider.of<TimeService>(context).getTheme;
User user = Provider.of<User>(context);
return FutureBuilder<UserData>(
future: DatabaseService(uid: user.uid).userData,
builder: (context, snapshot) {
while (!snapshot.hasData) {
return Loading();
}
UserData userData = snapshot.data;
return Scaffold(
appBar: AppBar(
backgroundColor: Theme.of(context).primaryColor,
title: Text('MyApp',
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 27,
)),
centerTitle: true,
actions: <Widget>[
new FlatButton(
child:Text('Log Out',
style: new TextStyle(fontSize: 18.0, color: Colors.black)),
onPressed: () {
print("Log Out"),
}),
],
),
drawer: Drawer(
child: ListView(
padding: EdgeInsets.zero,
children: <Widget>[
DrawerHeader(
decoration: BoxDecoration(color: Theme.of(context).primaryColor),
child: Column(
children: <Widget>[
CircleAvatar(
backgroundColor: Color(0xFF222222),
child: Text(
'${userData.firstName.substring(0, 1).toUpperCase()}${userData.lastName.substring(0, 1).toUpperCase()}',
style: TextStyle(color: Colors.grey, fontSize: 48),
),
radius: 50.0,
),
SizedBox(
height: MediaQuery.of(context).size.width * 0.02,
),
Text(
"${userData.firstName} ${userData.lastName}",
style: TextStyle(fontSize: 22),
),
],
),
),
],
),
),
body: (currentPosition != null)
? Stack(
children: <Widget>[
GoogleMap(
onMapCreated: (GoogleMapController controller) {
mapController = controller;
if (mapChange == false) {
rootBundle
.loadString('lib/assets/maps/DarkStyle.txt')
.then((string) {
_mapStyle = string;
});
} else {
rootBundle
.loadString('lib/assets/maps/LightStyle.txt')
.then((string) {
_mapStyle = string;
});
}
mapController.setMapStyle(_mapStyle);
},
myLocationEnabled: true,
myLocationButtonEnabled: true,
initialCameraPosition: CameraPosition(
target: LatLng(
currentPosition.latitude, currentPosition.longitude),
zoom: 12.0,
),
zoomGesturesEnabled: true,
),
],
)
: Center(child: Loading()),
);
});
}
}
如您所见,它非常依赖数据库服务,即此代码。
class DatabaseService {
final String uid;
DatabaseService({this.uid});
// collection reference
final CollectionReference userCollection =
Firestore.instance.collection('Users');
Future<void> createUserData(String firstName, String lastName, String email,
Timestamp birthDay) async {
return await userCollection.document(uid).setData({
"id": uid,
"email": email,
"firstName": firstName,
"lastName": lastName,
"birthdDay": birthDay,
"driver": false,
"business": false,
"admin": false,
"towTruck": false,
"orders": orders,
"homeLocation": null,
"activeLanguage": false,
"activeTheme": false,
"dateCreated": Timestamp.fromDate(DateTime.now()),
});
}
// user data from snapshots
UserData _userDataFromSnapshot(DocumentSnapshot snapshot) {
return UserData(
uid: snapshot.data['id'],
email: snapshot.data['email'],
firstName: snapshot.data['firstName'],
lastName: snapshot.data['lastName'],
birthDay: snapshot.data['birthday'],
driver: snapshot.data['driver'],
business: snapshot.data['business'],
admin: snapshot.data['admin'],
orders: snapshot.data['orders'],
towTruck: snapshot.data['towTruck'],
homeLocation: snapshot.data['towTruck'],
activeLanguage: snapshot.data['activeLanguage'],
activeTheme: snapshot.data['activeTheme']);
}
// get user doc stream
Future<UserData> get userData async {
DocumentReference userReference = userCollection.document(uid);
DocumentSnapshot userRef = await userReference.get();
return _userDataFromSnapshot(userRef);
}
}
如果有人能解释如何解决这个问题,如果有机会将其更改为流,我将不胜感激,我也将不胜感激。
我对飞镖很陌生,颤振非常感谢解决方案的代码解释。