【问题标题】:Why I get a null object reference documentSnapshot.toObject() method?为什么我得到一个空对象引用 documentSnapshot.toObject() 方法?
【发布时间】:2018-12-14 23:17:03
【问题描述】:

我正在尝试为简单的登录/注册表单添加 firebase auth 和 firebase 数据库,但由于User currentUser = documentSnapshot.toObject(User.class); 返回一个空对象而导致崩溃,我不明白为什么。

这是我的代码 个人资料活动:

    package fr.tom_d.growthwatcher;


import android.os.Bundle;
import android.text.TextUtils;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ProgressBar;
import android.widget.TextView;

import com.google.android.gms.tasks.OnSuccessListener;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.firestore.DocumentSnapshot;

import fr.tom_d.growthwatcher.api.UserHelper;
import fr.tom_d.growthwatcher.models.User;


public class ProfilActivity extends BaseActivity {

    private static final int UPDATE_USERNAME = 30;
    private FirebaseAuth mAuth;
    private TextView mUsername;
    private EditText mNewUsername;
    private ProgressBar mProgressBar;
    private Button mButton;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mAuth = FirebaseAuth.getInstance();
        setContentView(R.layout.activity_profil);

        mUsername = findViewById(R.id.profile_tv_username);
        mNewUsername = findViewById(R.id.profile_et_username);
        mProgressBar = findViewById(R.id.profile_progressbar);
        mButton = findViewById(R.id.profile_change_username_btn);

        this.updateUIWhenCreating();

        mButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                updateUsernameInFirebase();
            }
        });
    }




    private void updateUIWhenCreating(){

        if (this.getCurrentUser() != null){

            //Get email & username from Firebase
            String username = TextUtils.isEmpty(this.getCurrentUser().getDisplayName()) ? getString(R.string.info_no_username_found) : this.getCurrentUser().getDisplayName();

            //Update views with data
            this.mUsername.setText(username);
        }
        UserHelper.getUser(this.getCurrentUser().getUid()).addOnSuccessListener(new OnSuccessListener<DocumentSnapshot>() {
            @Override
            public void onSuccess(DocumentSnapshot documentSnapshot) {
                User currentUser = documentSnapshot.toObject(User.class);
                String username = TextUtils.isEmpty(currentUser.getUsername()) ? getString(R.string.info_no_username_found) : currentUser.getUsername();
                mNewUsername.setText(username);
            }
        });
    }

    private void updateUsernameInFirebase(){

        String username = this.mNewUsername.getText().toString();

        if (this.getCurrentUser() != null){
            if (!username.isEmpty() &&  !username.equals(getString(R.string.info_no_username_found))){
                UserHelper.updateUsername(username, this.getCurrentUser().getUid()).addOnFailureListener(this.onFailureListener()).addOnSuccessListener(this.updateUIAfterRESTRequestsCompleted(UPDATE_USERNAME));
            }
        }
    }

    private OnSuccessListener<Void> updateUIAfterRESTRequestsCompleted(final int origin){
        return new OnSuccessListener<Void>() {
            @Override
            public void onSuccess(Void aVoid) {
                switch (origin){
                    // 8 - Hiding Progress bar after request completed
                    case UPDATE_USERNAME:
                        mProgressBar.setVisibility(View.INVISIBLE);
                        break;
                }
            }
        };
    }


}

用户:

    package fr.tom_d.growthwatcher.models;

import android.support.annotation.Nullable;

public class User {

    private String mUid;
    @Nullable
    private String mUsername;

    public User() { }

    public User(String uid, String username) {
        mUid = uid;
        mUsername = username;
    }

    // --- GETTERS ---
    public String getUid() { return mUid; }
    public String getUsername() { return mUsername; }

    // --- SETTERS ---
    public void setUsername(String username) { this.mUsername = username; }
    public void setUid(String uid) { this.mUid = uid; }
}

用户助手:

package fr.tom_d.growthwatcher.api;

import com.google.android.gms.tasks.Task;
import com.google.firebase.firestore.CollectionReference;
import com.google.firebase.firestore.DocumentSnapshot;
import com.google.firebase.firestore.FirebaseFirestore;

import fr.tom_d.growthwatcher.models.User;

public class UserHelper {

    private static final String COLLECTION_NAME = "users";

    // --- COLLECTION REFERENCE ---


    public static CollectionReference getUsersCollection() {
        return FirebaseFirestore.getInstance().collection(COLLECTION_NAME);
    }

    // --- CREATE ---

    public static Task<Void> createUser(String uid, String username) {
        User userToCreate = new User(uid, username);
        return UserHelper.getUsersCollection().document(uid).set(userToCreate);
    }

    // --- GET ---

    public static Task<DocumentSnapshot> getUser(String uid) {
        return UserHelper.getUsersCollection().document(uid).get();
    }

    // --- UPDATE ---

    public static Task<Void> updateUsername(String username, String uid) {
        return UserHelper.getUsersCollection().document(uid).update("username", username);
    }


    // --- DELETE ---

    public static Task<Void> deleteUser(String uid) {
        return UserHelper.getUsersCollection().document(uid).delete();
    }


}

我还注意到我的数据库 Firebase 是空的,而当我使用 Displayname 作为他的电子邮件地址注册时必须创建一个用户,如果他通过 google 登录,否则他在 EditText 中指示的昵称。然后我运行我的主要活动,该活动应该在数据库中创建一个用户 ....

我的mainActivity的代码:

package fr.tom_d.growthwatcher;

import android.content.Intent;
import android.support.annotation.NonNull;
import android.support.design.widget.CoordinatorLayout;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import android.support.design.widget.Snackbar;


import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.auth.FirebaseUser;
import com.jjoe64.graphview.GraphView;
import com.jjoe64.graphview.series.DataPoint;
import com.jjoe64.graphview.series.LineGraphSeries;

import fr.tom_d.growthwatcher.api.UserHelper;

public class MainActivity extends BaseActivity {

    private final static int RC_SIGN_IN = 100;

    private FirebaseAuth mAuth;
    private TextView mMail, mId;
    private EditText mPlantDate, mRelDate, mTempRel;
    private Button mPlantDateBtn, mTempRelBtn, mProfilBtn;
    private GraphView mGraph;
    private DataPoint[] mDataPoint;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        mAuth = FirebaseAuth.getInstance();

        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mMail = findViewById(R.id.main_mail);
        mId = findViewById(R.id.main_id);
        //mGraph = findViewById(R.id.main_graph);

        mPlantDate = findViewById(R.id.main_et_date_plant);
        mPlantDateBtn = findViewById(R.id.main_ok_plant_btn);

        mRelDate = findViewById(R.id.main_et_date_rel);
        mTempRel = findViewById(R.id.main_et_temp);
        mTempRelBtn = findViewById(R.id.main_ok_temp_btn);

        mProfilBtn = findViewById(R.id.main_profil_btn);

        //LineGraphSeries<DataPoint> series = new LineGraphSeries<>(mDataPoint);

        mPlantDateBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

            }
        });

        mProfilBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent profileActivity = new Intent(MainActivity.this, ProfilActivity.class);
                startActivity(profileActivity);
            }
        });
    }

    @Override
    public void onStart() {
        super.onStart();
        FirebaseUser currentUser = mAuth.getCurrentUser();
        String vEmail = currentUser.getEmail();
        String vId = currentUser.getProviderId();
        mMail.setText(vEmail);
        mId.setText(vId);
    }


    private void createUserInFirestore(){

        if (this.getCurrentUser() != null){

            String urlPicture = (this.getCurrentUser().getPhotoUrl() != null) ? this.getCurrentUser().getPhotoUrl().toString() : null;
            String username = this.getCurrentUser().getDisplayName();
            String uid = this.getCurrentUser().getUid();

            UserHelper.createUser(uid, username).addOnFailureListener(this.onFailureListener());
        }
    }

    private void handleResponseAfterSignIn(int requestCode, int resultCode, Intent data){

        if (requestCode == RC_SIGN_IN) {
            if (resultCode == RESULT_OK) {
                this.createUserInFirestore();
            } else {
                Toast.makeText(MainActivity.this, "ERREUR CREATION USER FIREBASE",
                        Toast.LENGTH_SHORT).show();
            }
        }
    }
}

注册活动:

package fr.tom_d.growthwatcher;

import android.content.Intent;
import android.support.annotation.NonNull;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;

import com.google.android.gms.auth.api.signin.GoogleSignIn;
import com.google.android.gms.auth.api.signin.GoogleSignInAccount;
import com.google.android.gms.auth.api.signin.GoogleSignInClient;
import com.google.android.gms.auth.api.signin.GoogleSignInOptions;
import com.google.android.gms.common.SignInButton;
import com.google.android.gms.common.api.ApiException;
import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.Task;
import com.google.firebase.auth.AuthCredential;
import com.google.firebase.auth.AuthResult;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.auth.FirebaseUser;
import com.google.firebase.auth.GoogleAuthProvider;
import com.google.firebase.auth.UserProfileChangeRequest;

import fr.tom_d.growthwatcher.api.UserHelper;

public class RegisterActivity extends BaseActivity {

    private final static String TAG = "RegisterActivity";
    private final static int RC_SIGN_IN = 100;


    private FirebaseAuth mAuth;
    private Button mStartButton;
    private TextView mAppText;
    private EditText mPseudo, mMail, mPassword;
    private boolean isPseudoOk, isPasswordOk, isMailOk;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mAuth = FirebaseAuth.getInstance();

        setContentView(R.layout.activity_register);

        isMailOk = false;
        isPasswordOk = false;
        isPseudoOk = false;


        mAppText = findViewById(R.id.register_app_text);
        mPseudo = findViewById(R.id.register_et_pseudo);
        mPassword = findViewById(R.id.register_et_password);
        mMail = findViewById(R.id.register_et_email);
        mStartButton = findViewById(R.id.register_start_button);

        mPseudo.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {

            }

            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {
                if(s.toString().length() >=3){
                    isPseudoOk=true;
                }
                if (isPseudoOk && isPasswordOk && isMailOk){
                    mStartButton.setEnabled(true);
                }
                else mStartButton.setEnabled(false);
            }

            @Override
            public void afterTextChanged(Editable s) {

            }
        });

        mPassword.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {

            }

            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {
                if (s.toString().length() >= 5){
                    isPasswordOk = true;
                }
                else isPasswordOk = false;

                if (isPseudoOk && isPasswordOk && isMailOk){
                    mStartButton.setEnabled(true);
                }
                else mStartButton.setEnabled(false);
            }

            @Override
            public void afterTextChanged(Editable s) {

            }
        });

        mMail.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {

            }

            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {
                if (s.toString().length() >= 5){
                    isMailOk = true;
                }
                else isMailOk = false;

                if (isPseudoOk && isPasswordOk && isMailOk){
                    mStartButton.setEnabled(true);
                }
                else mStartButton.setEnabled(false);
            }

            @Override
            public void afterTextChanged(Editable s) {

            }
        });

        mStartButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mAuth.createUserWithEmailAndPassword(mMail.getText().toString(), mPassword.getText().toString())
                        .addOnCompleteListener(RegisterActivity.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(TAG, "createUserWithEmail:success");
                                    UserProfileChangeRequest profileUpdates = new UserProfileChangeRequest.Builder()
                                            .setDisplayName(mPseudo.getText().toString()).build();
                                    getCurrentUser().updateProfile(profileUpdates);
                                    createUserInFirestore();
                                    Intent mainActivity = new Intent(RegisterActivity.this, MainActivity.class);
                                    startActivity(mainActivity);

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

    protected void onStart () {
        super.onStart();
        FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
        if (user != null) {
            Intent mainActivity = new Intent(RegisterActivity.this, MainActivity.class);
            startActivity(mainActivity);
        }
        else {
            // No user is signed in
        }
    }
}

【问题讨论】:

  • 因为 documentSnapshot 为空,您不能在空变量上调用方法。
  • @HirasawaYui 文档快照对象永远不会为空。但它可能引用确实存在的文档,您应该检查这种情况。
  • B-但是...错误...这意味着它为空...
  • 不,文档快照不为空,返回空的是toObject()方法
  • 您的 Firebase 中价值 mUid 的关键是什么?

标签: android firebase google-cloud-firestore


【解决方案1】:

根据toObject() 的 API 文档,如果文档不存在,它将返回 null。您应该首先使用exists() 检查它是否存在。

【讨论】:

  • 好的,谢谢,这是我的 handeSignInAfterRequest() 方法调用不当。但是现在我遇到了一个始终与 firebase 相关但与原始问题更相关的问题。我不明白为什么 getCurrentUser(). GetDisplayName() 会显示我在 TextView 中输入的用户名,但在之前的活动中却没有显示在另一个 TextView 中。此外,我的数据库创建了一个用户集合和一个带有 uid 但用户名字段为空的文档。但是,在调用createUserInFirestore() 方法之前,我会执行setDisplayName()。我在问题中添加了注册活动代码
猜你喜欢
  • 1970-01-01
  • 2014-12-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-05-11
  • 2015-05-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多