Using model class in flutter (dart)

笑着哭i 提交于 2021-01-29 12:57:08

问题


I'm trying to create a model class with a few methods to simplify retrieving information from Firebase.

I have a "Unregistered" page where user clicks on the "Login with google" button. If my user is already registered it checks the DB to see if he completed his profile, otherwise it writes basic data to the database with a field profileCompleted: false and redirects the user to the profile page so he can complete his profile.

I'm trying to use a model here, but i'm getting all sorts of errors (just started learning flutter/dart).

I'll share some code, let me know if its not enough!

Unregistered page.

    if (user != null) {
      await prefs.setString('id', user.uid);
      // Check is already sign up
      final QuerySnapshot result = await Firestore.instance
          .collection('users')
          .where('id', isEqualTo: user.uid)
          .getDocuments();
      final List<DocumentSnapshot> documents = result.documents;

      if (documents.length == 0) {
        debugPrint("User not in DB ?");
        //debugPrint(userInfo.toString());
        // Update data to server if new user

        Firestore.instance.collection('users').document(user.uid).setData({
          'id': user.uid,
          'nickname': user.displayName,
          'photoUrl': user.photoUrl,
          'email': user.email,
          'createdAt': DateTime.now(),
          'provider': user.providerId,
          'profileCompleted': false,
          'bloodType': 'A',
          'rhType': 'Negativ',
          'donatedBefore': 'Nu',
          'lastDonation': '0'
        });
        Navigator.push(
            context,
            MaterialPageRoute(
                builder: (context) => CompleteProfile(
                      currentUserId: user.uid,
                      userInfo: documents.single,
                    )));
      } else if (documents.single["profileCompleted"] == false) {
        Navigator.push(
            context,
            MaterialPageRoute(
                builder: (context) => CompleteProfile(
                      currentUserId: user.uid,
                      userInfo: documents.single,
                    )));
      } else {
        Navigator.push(
            context,
            MaterialPageRoute(
                builder: (context) => HomePage(
                      currentUserId: user.uid,
                      userInfo: documents.single,
                    )));
      }
    }

Complete profile page

class CompleteProfile extends StatefulWidget {
  final String currentUserId;
  final userInfo;
  static const routeName = '/profile';
  final User user;

  CompleteProfile(
      {Key key,
      this.title,
      @required this.currentUserId,
      @required this.userInfo,
      this.user})
      : super(key: key);

  final String title;

  @override
  _CompleteProfileState createState() => _CompleteProfileState(user,
      currentUserId: this.currentUserId, userInfo: this.userInfo);
}

class _CompleteProfileState extends State<CompleteProfile> {
  User user;

  _CompleteProfileState(this.user,
      {Key key, @required this.currentUserId, @required this.userInfo});
  final String currentUserId;
  final userInfo;

My issue here is that if i try to set a dropdown like this ->

child: ListTile(
title: DropdownButton<String>(
items: _bloodTypes.map((String value) {
return DropdownMenuItem<String>(
value: value, child: Text(value));
}).toList(),
style: textStyle,
value: retrieveBloodType(user.bloodType),
onChanged: (value) => updateBloodType(value),

And on default value->

  String retrieveBloodType(String value) {
    return _bloodType;
  }

I get an error that i'm getting on null.

My idea was to initialize the User model with something like User user = new User(userInfo["id"],userInfo["email"].... in which userInfo is an object retrieved from firebase. However, that throws another error that only static members can be accessed in initalizers.

My model is quite simple so here's a sneak peek (few lines, not the entire model).

class User {
  int _id;
  String _nickname;
  int get id => _id;
  String get nickname => _nickname;
  set bloodType(String newBloodType) {
    if (newBloodType.length <= 50 && newBloodType != null) {
      _bloodType = newBloodType;
    }
  }

Any idea on how id have to change this to work? The only reason i'm thinking of using models is to simplify screen widgets (so i can add all firebase logic to the model instead of the widgets).


回答1:


This is how I would do it

import 'package:cloud_firestore/cloud_firestore.dart';

class User {
  final String userName;
  final String email;
  final String name;
  final String phoneNumber;
  final String profilePictureUrl;
  final Timestamp creationDate;

  const User(
    this.userName,
    this.email,
    this.name,
    this.phoneNumber,
    this.profilePictureUrl,
    this.creationDate
  );

  factory User.fromDocument(DocumentSnapshot document) {
    return User(
      document['userName'],
      document['email'],
      document['name'],
      document['phoneNumber'],
      document['profilePictureUrl'],
      document['creationDate']
    );
  }



回答2:


it would be better if your model looks like that:

class User {
  final String userName;
  final String email;


  User({
    this.userName,
    this.email,
 
  });

 User.fromMap(Map map)
  : this(
     userName : map['userName'],
     email : map['email'],
   );

 Map<Stringm dynmic> asMap() => {
   'userName' : userName,
   'email' : email,
  }

then you can use this model to set data to firebase as follow

Firestore.instance.collection('users').document(user.uid).setData(user.asMap)


来源:https://stackoverflow.com/questions/58146158/using-model-class-in-flutter-dart

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!