簡體   English   中英

文檔路徑必須是非空字符串,Flutter - Firebase錯誤?

[英]A document path must be a non-empty string, Flutter - Firebase error?

我在 flutter 和 firebase 上有一些錯誤,如果有人能幫忙就太好了,這是我的身份驗證 controller

class AuthController extends GetxController {
  final FirebaseAuth auth = FirebaseAuth.instance;
  final Rxn<User> _firebaseUser = Rxn<User>();
  Rx<XFile>? _pickedImage;

  XFile? get profilePhoto => _pickedImage?.value;
  // final user = FirebaseAuth.instance.currentUser.obs;

  Rxn<User> get user => _firebaseUser;
  // final user = FirebaseAuth.instance.currentUser;

  @override
  onInit() {
    _firebaseUser.bindStream(auth.authStateChanges());
    super.onInit();
  }

  // void register(
  //     String name, String email, String password, XFile? image) async {
  //   try {
  //     UserCredential _authResult = await auth.createUserWithEmailAndPassword(
  //         email: email.trim(), password: password);

  //     //create user in database.dart

  //     String downloadUrl = await uploadToStorage(image!);

  //     UserModel _user = UserModel(
  //       id: _authResult.user?.uid,
  //       name: name,
  //       email: _authResult.user?.email,
  //       profilePic: downloadUrl,
  //     );

  //     if (await Database().createNewUser(_user)) {
  //       Get.find<UserController>().user = _user;
  //     }
  //   } catch (e) {
  //     Get.snackbar(
  //       "Error creating Account",
  //       e.toString(),
  //       snackPosition: SnackPosition.BOTTOM,
  //     );
  //   }
  // }
  void register(
      String name, String email, String password, XFile? image) async {
    try {
      if (name.isNotEmpty &&
          email.isNotEmpty &&
          password.isNotEmpty &&
          image != null) {
        // save out user to our ath and firebase firestore
        UserCredential _authResult = await auth.createUserWithEmailAndPassword(
          email: email,
          password: password,
        );
        String downloadUrl = await uploadToStorage(image);
        UserModel _user = UserModel(
          id: _authResult.user?.uid,
          name: name,
          email: _authResult.user?.email,
          profilePic: downloadUrl,
        );
        if (await Database().createNewUser(_user)) {
          Get.find<UserController>().user = _user;
        } else {
          Get.snackbar(
            'Error Creating Account',
            'Please enter all the fields',
          );
        }
      }
    } catch (e) {
      Get.snackbar(
        'Error Creating Account',
        e.toString(),
      );
    }
  }

  void login(String email, password) async {
    try {
      UserCredential _authResult = await auth.signInWithEmailAndPassword(
          email: email.trim(), password: password);
      Get.find<UserController>().user =
          await Database().getUser(_authResult.user?.uid ?? '');
    } catch (e) {
      Get.snackbar("About User", "User message",
          snackPosition: SnackPosition.BOTTOM,
          titleText: Text("Acount creation failed"),
          messageText:
              Text(e.toString(), style: TextStyle(color: Colors.white)));
    }
  }

  Future<void> signOut() async {
    await auth.signOut();
    Get.find<UserController>().clear();
  }

  Future pickImage() async {
    print("call on click add photo icon");
    final ImagePicker _picker = ImagePicker();
    final XFile? pickedImage =
        await _picker.pickImage(source: ImageSource.gallery);
    print('picked image filled with image from gallery'); //This doesnt print at

    if (pickedImage != null) {
      Get.snackbar('Profile Picture',
          'You have successfully selected your profile picture!');

      // print(pickedImage.path);
    }
    _pickedImage = Rx<XFile>(pickedImage!);
    // print(_pickedImage);
    // print(profilePhoto);
  }

  // upload to firebase storage
  Future<String> uploadToStorage(XFile? image) async {
    Reference ref = FirebaseStorage.instance
        .ref('')
        .child('profilePics')
        .child(auth.currentUser!.uid);

    // print(ref);

    UploadTask uploadTask = ref.putFile(File(image?.path ?? 'idemo'));
    print(uploadTask);
    // TaskSnapshot snap = await uploadTask;
    String downloadUrl = await (await uploadTask).ref.getDownloadURL();
    print(downloadUrl);
    return downloadUrl;
  }
}

這是我的 function 來創建新用戶

class Database {
  final FirebaseFirestore _firestore = FirebaseFirestore.instance;

  Future<bool> createNewUser(UserModel user) async {
    try {
      await _firestore.collection("users").doc(user.id).set({
        "name": user.name,
        "email": user.email,
        "profilePhoto": user.profilePic
      });
      return true;
    } catch (e) {
      print(e);
      return false;
    }
  }

這是家庭控制器

class HomeController extends GetxController {
  final Rxn<List<TodoModel>> todoList = Rxn<List<TodoModel>>([]);

  var selectedDate = DateTime.now().obs;

  List<TodoModel>? get todos => todoList.value;

  @override
  void onInit() {
    super.onInit();
    String? uid = Get.find<AuthController>().auth.currentUser?.uid ?? '';
    print(uid);
    todoList.bindStream(Database().todoStream(uid));
  }

  chooseDate() async {
    DateTime? pickedDate = await showDatePicker(
      context: Get.context!,
      initialDate: selectedDate.value,
      firstDate: DateTime(2000),
      lastDate: DateTime(2024),
      //initialEntryMode: DatePickerEntryMode.input,
      // initialDatePickerMode: DatePickerMode.year,
    );
    if (pickedDate != null && pickedDate != selectedDate.value) {
      selectedDate.value = pickedDate;
    }
  }
}

這是查看頁面

GetX<HomeController>(
  init: Get.put<HomeController>(HomeController()),
  builder: (HomeController todoController) {
    if (todoController.todos != null) {
      // print(todoController.todos?.done ?? false);
      return Expanded(
        child: ListView.builder(
          itemCount: todoController.todos?.length,
          itemBuilder: (_, index) {
            return TodoCard(
              uid: controller.user.value?.uid ?? '',
              todo: todoController.todos![index],
            );
          },
        ),
      );
    } else {
      return Text("loading...");
    }
  },
),

所以,當我注冊一個新用戶時出現錯誤,我收到了這個錯誤:

Building Builder(dirty) 引發了以下斷言:文檔路徑必須是非空字符串斷言失敗:第 116 行第 14 行:'path.isNotEmpty'

這是來自終端的 output:

The relevant error-causing widget was
GetMaterialApp
lib/main.dart:23
When the exception was thrown, this was the stack
#2      _JsonCollectionReference.doc
#3      Database.todoStream
#4      HomeController.onInit
#5      GetLifeCycleBase._onStart
#6      InternalFinalCallback.call
#7      GetInstance._startController
#8      GetInstance._initDependencies
#9      GetInstance.find
#10     GetInstance.put
#11     Inst.put

所以這個路徑有問題,當我從 visual studio 重新加載時,我用正確的數據向正確的用戶求助。 所以問題是當我第一次注冊用戶時。

看起來uid是空的,您也應該可以通過查找print(uid);看到這一點。 在您的 output 中。

當您的應用程序或 web 頁面加載時,Firebase 會自動嘗試從其本地 state 恢復先前登錄的用戶。然而,這需要它調用服務器(例如檢查帳戶是否已被禁用)並且在調用時正在進行,您的主要代碼將繼續執行,並且currentUser變量將變為null

您的代碼需要考慮到這一點。 執行此操作的最簡單方法是不依賴於currentUser ,而是使用響應式響應身份驗證 state 中的更改,如有關獲取當前用戶的文檔中的第一個示例所示:

FirebaseAuth.instance
  .authStateChanges()
  .listen((User? user) {
    if (user != null) {
      print(user.uid);
    }
  });

此處的authStateChange方法返回一個 stream,它會在身份驗證 state 更改時觸發一個事件,因此當用戶登錄或注銷時。 使用此 stream 的常見方法是將用戶設置為小部件的 state,或者直接在 StreamBuilder 中使用StreamBuilder

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM