【问题标题】:Firebase Android error: Can't pass null for argument 'pathString' in childFirebase Android 错误:无法为子项中的参数“pathString”传递 null
【发布时间】:2021-01-03 19:58:36
【问题描述】:

当我通过注册表单在 firebase 上创建新用户时出现此错误:

java.lang.NullPointerException:不能在 child() 中为参数“pathString”传递 null

我在 google 和 YouTube 上搜索此错误,但没有找到适合我的程序的内容。

这是我在 SignUpActivity.java 上的部分代码:

    final EditText email = findViewById(R.id.email_address);
    final EditText display_name = findViewById(R.id.display_name);
    final EditText password = findViewById(R.id.pass_sign_up);
    final EditText comfirm_pass = findViewById(R.id.comfirm_pass);
    final Button submit = findViewById(R.id.submit_btn_signup);
    final TextView signin = findViewById(R.id.textView8);
    final FirebaseAuth mAuth = FirebaseAuth.getInstance();
    final String[] error = new String[1];
    final ProgressBar loading_icon = findViewById(R.id.progressBar2);


    // hide loading icon \\
    loading_icon.setVisibility(View.GONE);

    signin.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Intent intent = new Intent(SignupActivity.this,MainActivity.class);
            startActivity(intent);
        }
    });

    submit.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            loading_icon.setVisibility(View.VISIBLE);

            String email_input = email.getText().toString();
            String display_name_input = display_name.getText().toString();
            String password_input = password.getText().toString();
            String comfirm_pass_input = comfirm_pass.getText().toString();

            if (email_input.isEmpty() || display_name_input.isEmpty() || password_input.isEmpty() || comfirm_pass_input.isEmpty()){
                error[0] = "Please fill all the values and try again";
                Toast.makeText(SignupActivity.this, error[0], Toast.LENGTH_LONG).show();
                loading_icon.setVisibility(View.GONE);
            }else{
                if (!password_input.equals(comfirm_pass_input)){
                    error[0] = "passwords do not match";
                    Toast.makeText(SignupActivity.this, error[0], Toast.LENGTH_LONG).show();
                    loading_icon.setVisibility(View.GONE);
                }else{
                    mAuth.createUserWithEmailAndPassword(email_input,password_input).addOnCompleteListener(new OnCompleteListener<AuthResult>() {
                        @Override
                        public void onComplete(@NonNull @NotNull Task<AuthResult> task) {
                            if (task.isSuccessful()){
                                finish();
                                // set display name for user \\
                                FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
                                UserProfileChangeRequest profileUpdates = new UserProfileChangeRequest.Builder()
                                        .setDisplayName(display_name_input).build();
                                user.updateProfile(profileUpdates);

                                DatabaseReference mRef = FirebaseDatabase.getInstance().getReference();

                                mRef.addValueEventListener(new ValueEventListener(){
                                    @Override
                                    public void onDataChange(@NotNull DataSnapshot dataSnapshot){

                                        // Get the max_user_id to set the main user id and create the user on Firebase real-time DB \\
                                        String maxUserId = dataSnapshot.child("max_user_id").getValue().toString();
                                        int maxUserIdToInt = Integer.parseInt(maxUserId);
                                        int userId = maxUserIdToInt+1;
                                        newUserId = String.valueOf(userId);
                                        mRef.child("users").child(newUserId).child("name").setValue(display_name_input);
                                    }

                                    @Override
                                    public void onCancelled(@NotNull DatabaseError databaseError){
                                        Toast.makeText(SignupActivity.this,"error: " + databaseError, Toast.LENGTH_LONG).show();
                                    }
                                });

                                mRef.child("users").child(newUserId);
                                

                                Intent intent = new Intent(SignupActivity.this,HomeActivity.class);
                                startActivity(intent);
                            }else{
                                loading_icon.setVisibility(View.GONE);
                                error[0] = "failed to sign up, the email address aleready exist or the password lenght is lower than 6 characters";
                                Toast.makeText(SignupActivity.this, error[0], Toast.LENGTH_LONG).show();
                            }
                        }
                    });
                }
            }
        }
    });

}

}

注意:我是 Android 应用程序的 firebase 初学者。我今天也在这里创建了我的帐户,stackoverflow 非常酷且乐于助人

【问题讨论】:

    标签: java android firebase firebase-realtime-database mobile


    【解决方案1】:

    调用child()时,需要传入一个非空的String作为参数。在您的情况下,newUserId 出于某种原因为空。因此你调用child(newUserId),Firebase 会抛出异常。

    接下来应该检查您使用路径max_user_id 访问孩子的方式是否正确。您可以在该位置保留一个断点,然后通过dataSnapshot 的结构来获取正确的路径。

    【讨论】:

    • 我在数据库中写了一个具有此名称的变量,我尝试从字符串中获取它的 int 值,并且从字符串到 int 的转换可能存在问题。这就是为什么可能是 null
    【解决方案2】:

    问题出在这个片段的最后一行:

    DatabaseReference mRef = FirebaseDatabase.getInstance().getReference();
    
    mRef.addValueEventListener(new ValueEventListener(){
        @Override
        public void onDataChange(@NotNull DataSnapshot dataSnapshot){
    
            // Get the max_user_id to set the main user id and create the user on Firebase real-time DB \\
            String maxUserId = dataSnapshot.child("max_user_id").getValue().toString();
            int maxUserIdToInt = Integer.parseInt(maxUserId);
            int userId = maxUserIdToInt+1;
            newUserId = String.valueOf(userId);
            mRef.child("users").child(newUserId).child("name").setValue(display_name_input);
        }
    
        @Override
        public void onCancelled(@NotNull DatabaseError databaseError){
            Toast.makeText(SignupActivity.this,"error: " + databaseError, Toast.LENGTH_LONG).show();
        }
    });
    
    mRef.child("users").child(newUserId);
    

    该行没有任何意义,但它在newUserId = String.valueOf(userId) 之前执行,这意味着您传入了一个初始化的newUserId,这会导致错误消息。

    由于mRef.child("users").child(newUserId); 这行无论如何都没有做任何事情,所以您可以安全地删除它。

    作为一般规则:您应该只在onDataChange 内或从那里调用的代码中使用newUserId。出于这个原因,我建议将其设置为 onDataChange 中的局部变量,而不是字段或其他更广泛的范围。如需详细了解为什么会这样,请参阅 Is it possible to synchronously load data from Firebase?Setting Singleton property value in Firebase Listener

    【讨论】:

    • 如果我理解正确,您的意思是从方法中取出变量,只留下变量 newUserId 并在我在 Firebase db 中添加变量时删除该行。但是我添加了这一行,因为我想什么时候可以用这种方法在 db 上添加一个变量,但也许我错了。那么我如何在实时数据库中创建一个新用户呢??。谢谢
    • 只有在调用 setValue 时才会写入数据,这是在 onDataChange 内部进行的,其中 newUserId 已初始化(据我所知)。如果您在mRef.child("users").child(newUserId); 上设置断点并在调试器中运行应用程序,您将看到newUserId 没有值,因为onDataChange 尚未运行。请阅读我在回答中提供的链接,因为我在那里进行了更详细的解释。
    猜你喜欢
    • 2020-11-05
    • 1970-01-01
    • 2020-01-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-25
    相关资源
    最近更新 更多