【问题标题】:Why I can't record first and last records on an array to Firestore为什么我不能将数组上的第一条和最后一条记录记录到 Firestore
【发布时间】:2018-09-06 12:37:35
【问题描述】:

我正在尝试在 Firebase Firestore 上注册 20 个用户并在我的集合中为每个用户创建一个文档。我的程序成功注册了 20 个用户,但在为他们创建文档时失败了。 18, 每次创建 19 个文档,但它几乎总是跳过为我的数组的第一个成员和最后一个成员创建一个文档。 StudentCreator 只是一个文件,它有一个父数组,有 20 个项目的学生数组。 这是一个来自 studentCreator.java 的数组

public static String parent_names[]={ "Ahmet Lola", "Hüseyin Kutlutürk", "Ümit Uğrak", "Veysel Karani", "Serkan Gotar", "Dündar Zalim", "Kadir Berkay", "Uğur Özdemir", "Bünyamin Akgün", "Kaptan Price", "Selim Tekiner", "Gökçe Yılan", "Talip Özkan", "Abdurrahman Tarikçi", "Selim Kirlier", "Hasan Can Doğan", "Erdem Gökşen", "Fatoş Ünal", "Nurgül Birtek", "Yuan Hui"};

这里是主要代码:

    public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
private FirebaseAuth mAuth;
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    final Intent LoginActivity = new Intent(this,LoginActivity.class);
    final Intent TeacherActivity = new Intent(this,TeacherActivity.class);
    final Intent ParentActivity = new Intent(this,ParentActivity.class);
    final Intent ManagerActivity = new Intent(this,ManagerActivity.class);


    for (int i = 0; i < 20; i++)
    {
        mAuth = FirebaseAuth.getInstance();
        final String username = StudentCreator.parent_names[i].replaceAll(" ", "") + StudentCreator.student_numbers[i];
        final String email = username + "@onurmail.com";
        final String password = "123456";

        final String student_name = StudentCreator.student_names[i];
        final String parent_name = StudentCreator.parent_names[i];
        //Registration is successul here.
        mAuth.createUserWithEmailAndPassword(email, password)
                .addOnCompleteListener(this, new OnCompleteListener<AuthResult>() {
                    @Override
                    public void onComplete(@NonNull Task<AuthResult> task) {
                        if (task.isSuccessful()) {
                            // Sign in success, update UI with the signed-in user's information
                            Log.d("User Registered", "createUserWithEmail:success");

                            final FirebaseUser user = mAuth.getCurrentUser();
                            final String user_id = user.getUid();
                            //I get valid userId's for 20 users.
                            //CREATE STUDENT OBJECT AND FIREBASE INSTANCES
                            final FirebaseFirestore db = FirebaseFirestore.getInstance();

                            final Map<String, Object> student = new HashMap<>();
                            student.put("student_name", student_name);
                            student.put("parent_name", parent_name);
                            //My first element of array comes here and prints its parent name and student name perfectly but cant see anything about it on database.
                            //PUT STUDENT TO THE DB
                            db.collection("TED_Ankara")
                                    .document(parent_name)
                                    .set(student)
                                    .addOnCompleteListener(new OnCompleteListener<Void>() {
                                        @Override
                                        public void onComplete(@NonNull Task<Void> task) {
                                            if (task.isSuccessful()) {
                                                Toast.makeText(getApplicationContext(), "User  inserted sucessfully: "+parent_name,
                                                        Toast.LENGTH_SHORT).show();

                                            }
                                            else {
                                                Toast.makeText(getApplicationContext(), "User cannot be inserted: "+parent_name,
                                                        Toast.LENGTH_SHORT).show();
                                            }

                                        }
                                    });

                            //PUT STUDENT TO THE DB



                        } else {
                            // If sign in fails, display a message to the user.
                            Log.w(TAG, "createUserWithEmail:failure", task.getException());
                            Toast.makeText(getApplicationContext(), "Authentication failed.",
                                    Toast.LENGTH_SHORT).show();
                        }

                    }

                });

    }
  }
}

请帮忙。我对 addOnCompleteListener 和 firebaseAuth 的使用持怀疑态度。但我不确定。感谢您的帮助。

编辑:在没有 for 循环的情况下添加第一个成员没有任何问题。所以我想问题出在 for 循环上。

【问题讨论】:

    标签: android firebase nosql firebase-authentication google-cloud-firestore


    【解决方案1】:

    Firebase SDK 只能有一个活跃用户。由于您在所谓的紧密循环中运行数组,我怀疑您可能正在创建下一个用户,在代码开始为前一个用户编写文档之前。为了验证这是否确实是问题,您可以尝试看看这是否解决了它?

    添加创建用户的函数

    void createNextUser(List<String> student_names, List<String> student_numbers, List<String> parent_names) {
      if (student_names.size() > 0 && student_numbers.size() > 0 && parent_names.size() > 0) {
        final String student_name = student_names.remove(0);
        final String student_number = student_numbers.remove(0);
        final String parent_name = parent_names.remove(0);
        final String username = parent_name.replaceAll(" ", "") + student_number;
        final String email = username + "@onurmail.com";
        final String password = "123456";
    
    
        mAuth.createUserWithEmailAndPassword(email, password)
            .addOnCompleteListener(this, new OnCompleteListener<AuthResult>() {
                @Override
                public void onComplete(@NonNull Task<AuthResult> task) {
                    if (task.isSuccessful()) {
                        // Sign in success, update UI with the signed-in user's information
                        Log.d("User Registered", "createUserWithEmail:success");
    
                        final FirebaseUser user = mAuth.getCurrentUser();
                        final String user_id = user.getUid();
                        //I get valid userId's for 20 users.
                        //CREATE STUDENT OBJECT AND FIREBASE INSTANCES
                        final FirebaseFirestore db = FirebaseFirestore.getInstance();
    
                        final Map<String, Object> student = new HashMap<>();
                        student.put("student_name", student_name);
                        student.put("parent_name", parent_name);
                        //My first element of array comes here and prints its parent name and student name perfectly but cant see anything about it on database.
                        //PUT STUDENT TO THE DB
                        db.collection("TED_Ankara")
                                .document(parent_name)
                                .set(student)
                                .addOnCompleteListener(new OnCompleteListener<Void>() {
                                    @Override
                                    public void onComplete(@NonNull Task<Void> task) {
                                        if (task.isSuccessful()) {
                                            Toast.makeText(getApplicationContext(), "User  inserted sucessfully: "+parent_name,
                                                    Toast.LENGTH_SHORT).show();
    
                                        }
                                        else {
                                            Toast.makeText(getApplicationContext(), "User cannot be inserted: "+parent_name,
                                                    Toast.LENGTH_SHORT).show();
                                        }
    
                                        // Now that we're done with this user, move on to the next one
                                        createNextUser(student_names, student_number, parent_names);
                                    }
                                });
    
                    } else {
                        // If sign in fails, display a message to the user.
                        Log.w(TAG, "createUserWithEmail:failure", task.getException());
                        Toast.makeText(getApplicationContext(), "Authentication failed.",
                                Toast.LENGTH_SHORT).show();
                    }
    
                }
    
            });    
      }
    }
    

    此代码的最大区别在于,它仅在创建前一个用户及其文档后才开始创建下一个用户。它通过以下方式做到这一点:

    1. 在开始时从列表中删除当前学生

      final String student_name = student_names.remove(0);
      final String student_number = student_numbers.remove(0);
      final String parent_name = parent_names.remove(0);
      
    2. 写完文档后调用自己

      // Now that we're done with this user, move on to the next one
      createNextUser(student_names, student_number, parent_names);
      

    现在剩下要做的就是在您的onCreate 中启动进程:

    createNextUser(Arrays.asList(StudentCreator.student_names), Arrays.asList(StudentCreator.student_numbers), Arrays.asList(StudentCreator.parent_names));
    

    注意:为其他用户创建帐户是一项管理操作,因此通常不应从 Android 客户端执行。我强烈建议查看Firebase Admin SDK,它对此类操作有更好的支持。它必须在受信任的环境中使用,而不是在 Android 应用程序中使用,例如您的开发机器、您控制的服务器或 Cloud Functions。

    【讨论】:

    • 非常感谢您的回复。我很高兴能从真正的专业人士那里得到答案。据我了解,使用循环创建一些文档是一种不好的态度,我今晚将开始使用 Admin SDK。我只是想问一下,在创建文档时,我的程序不应该在 addOnCompleteListener 处停止吗为那个用户?据我了解,无论如何它都应该在那里等待。不是这样吗?它只是继续循环并跳过听众吗?
    • 程序没有停止。用户和文档的创建是异步进行的,一旦完成,您的onComplete 就会被调用。但是你的循环没有被阻塞,所以它会立即启动所有 20 个循环。我的代码使它们按顺序排列:一个接一个。
    猜你喜欢
    • 2017-05-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-15
    相关资源
    最近更新 更多