[英]Null pointer with Firebase auth. How to put listener to another class
Trying to implement firebase auth.尝试实施 Firebase 身份验证。 It was working before but after refactoring no.它之前有效,但在重构之后没有。 So I tried to create authStateListener in a separate class and there I am checking the statement.所以我试图在一个单独的类中创建 authStateListener 并且我正在检查该语句。 MainActivity主要活动
IMainPresenter iMainPresenter;
iMainPresenter = new MainPresenter();
iMainPresenter.forwardInfoForLoginAuth(MainActivity.this);
In presenter在主持人
public class MainPresenter implements IMainPresenter{
AuthStateListenerUtil authStateListenerUtil;
public MainPresenter() {
this.authStateListenerUtil = authStateListenerUtil;
}
@Override
public void forwardInfoForLoginAuth(Activity mainActivity) {
AuthStateListenerUtil authStateListenerUtils = new AuthStateListenerUtil();
authStateListenerUtils.checkForAuthState(mainActivity);
}
}
And the class which has to check the state of the user and in case that user is not logged in it has to show login window并且必须检查用户状态的类,如果用户未登录,则必须显示登录窗口
public void checkForAuthState(final Activity mainActivity){
Log.v("==========>", " IN CHECK FOR METHOD");
new FirebaseAuth.AuthStateListener() {
@Override
public void onAuthStateChanged(@NonNull FirebaseAuth firebaseAuth) {
if (FirebaseUserUtil.currentUser != null) {
//Create new user
final String userName = FirebaseUserUtil.currentUser.getDisplayName();
FirebaseUserUtil.getCurrentUserUid(FirebaseUserUtil.userUid)
.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
//the image is still the default one
HashMap<String, String> userMap = new HashMap<>();
userMap.put("name", userName);
userMap.put("image", "default");
userMap.put("thumb_image", "default");
userMap.put("status", "Your status is here...");
FirebaseUserUtil.getCurrentUserUid(FirebaseUserUtil.userUid).setValue(userMap);
}
@Override
public void onCancelled(DatabaseError databaseError) {}
});
} else {
mainActivity.startActivityForResult(
AuthUI.getInstance()
.createSignInIntentBuilder()
.setAvailableProviders(Arrays.asList(
new AuthUI.IdpConfig.EmailBuilder().build(),
new AuthUI.IdpConfig.GoogleBuilder().build()))
.build(),
RC_SIGN_IN);
}
}
};
}
I am trying to initialize all main queries in one class to avoid duplicating on each activity.我试图在一个类中初始化所有主要查询,以避免在每个活动上重复。 In future I will refactor it to dagger2 but right now I am using regular classes.将来我会将它重构为 dagger2,但现在我正在使用常规类。 So thats the query class这就是查询类
public class FirebaseUserUtil {
public static FirebaseUser currentUser = FirebaseAuth.getInstance().getCurrentUser();
public static String currentUserUid = currentUser.getUid();
public static DatabaseReference getCurrentUserUid(){
return FirebaseDatabase.getInstance().getReference().child("Users").child(currentUserUid);
}
static String getCurrentUserUidString(String uid){
String currentUid = FirebaseDatabase.getInstance().getReference().child("Users").child(currentUserUid).toString();
return currentUid;
}
}
In logs it shows me tag "IN CHECK FOR METHOD" so I made a conclusion that threw presenter it finds this method but it crashes.在日志中,它向我显示了“IN CHECK FOR METHOD”标签,所以我得出了一个结论,让演示者找到了这个方法,但它崩溃了。 Also, I thought that it might be a problem with firebase database.另外,我认为这可能是 firebase 数据库的问题。 So I removed everything from there.所以我从那里删除了所有东西。 So if I understand right if the table in firebase is empty after user login it has to create a new table with data.因此,如果我理解正确,如果用户登录后 firebase 中的表为空,则必须创建一个包含数据的新表。 Also the problem is that error which I can see in logcat don't give me a link or information where is the mistake.还有一个问题是我在 logcat 中看到的错误没有给我一个链接或信息,错误在哪里。
FATAL EXCEPTION: main
Process: com.borisruzanov.russianwives, PID: 6777
java.lang.NullPointerException: Attempt to invoke interface method 'void com.google.firebase.auth.FirebaseAuth$AuthStateListener.onAuthStateChanged(com.google.firebase.auth.FirebaseAuth)' on a null object reference
at com.google.firebase.auth.zzi.run(Unknown Source)
at android.os.Handler.handleCallback(Handler.java:751)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6119)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776)
My App class我的应用类
public class App extends Application{
private DatabaseReference mUserDatabase;
private FirebaseAuth mAuth;
@Override
public void onCreate() {
super.onCreate();
FirebaseDatabase.getInstance().setPersistenceEnabled(true);
/* Picasso */
Picasso.Builder builder = new Picasso.Builder(this);
builder.downloader(new OkHttpDownloader(this, Integer.MAX_VALUE));
Picasso built = builder.build();
built.setIndicatorsEnabled(true);
built.setLoggingEnabled(true);
Picasso.setSingletonInstance(built);
mAuth = FirebaseAuth.getInstance();
if(mAuth.getCurrentUser() != null) {
mUserDatabase = FirebaseDatabase.getInstance()
.getReference().child("Users").child(mAuth.getCurrentUser().getUid());
mUserDatabase.addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
if (dataSnapshot != null) {
mUserDatabase.child("online").onDisconnect().setValue(ServerValue.TIMESTAMP);
}
}
@Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
}
}
For me it looks like that the error is in Database not in code.对我来说,错误似乎是在数据库中而不是在代码中。
If your behavior it's the same for all user state changes you've to use "addAuthStateListener".如果您的行为对于所有用户状态更改都相同,则您必须使用“addAuthStateListener”。
For AuthStateListener works you have to execute some of methods to authenticate ("signInWithEmailAndPassword", "createUserWithEmailAndPassword", ...).对于 AuthStateListener 工作,您必须执行一些方法来进行身份验证(“signInWithEmailAndPassword”、“createUserWithEmailAndPassword”、...)。
The best way to implement a FirebaseAuth is keeping an instance in your Presenter or Interactor of that object and program the same code block for all:实现 FirebaseAuth 的最佳方法是在该对象的 Presenter 或 Interactor 中保留一个实例,并为所有对象编写相同的代码块:
FirebaseAuth mAuth;
public MainPresenter() {
FirebaseAuth mAuth = FirebaseAuth.getInstance();
mAuth.addAuthStateListener(new FirebaseAuth.AuthStateListener() {
@Override
public void onAuthStateChanged(@NonNull FirebaseAuth firebaseAuth) {
/*
* put your code here
*/
}
});
}
Or addOnCompleteListener for each method of authentication (in this case signInWithEmailAndPassword).或者为每种身份验证方法添加OnCompleteListener(在本例中为signInWithEmailAndPassword)。
public void login(String email, String password){
mAuth.signInWithEmailAndPassword(email, password)
.addOnCompleteListener(new OnCompleteListener<AuthResult>() {
@Override
public void onComplete(@NonNull Task<AuthResult> task) {
Log.d(getClass().getSimpleName(), "signInWithEmail:onComplete:" + task.isSuccessful());
if (task.isSuccessful()) {
Log.w(getClass().getSimpleName(), "signInWithEmail", task.getException());
FirebaseUser user = mAuth.getCurrentUser();
if (user!=null) {
listener.onResult(null, user);
}
} else {
listener.onResult(task.getException(), null);
}
}
}).addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {
listener.onResult(e, null);
}
});
}
When you are using the floowing line of code:当您使用以下代码行时:
new FirebaseAuth.AuthStateListener() {/* ... */}
It means that you are creating a new instance of AuthStateListener
class but without assignin it to a variable.这意味着您正在创建AuthStateListener
类的新实例,但没有将其分配给变量。
So it gives you a NPE
because you using addAuthStateListener()
on an object that has the value of null
.所以它给了你一个NPE
因为你在一个值为null
的对象上使用addAuthStateListener()
。 To solve this, just asign new FirebaseAuth.AuthStateListener()
to you mAuth
field and then use it wherever you want.要解决这个问题,只需将new FirebaseAuth.AuthStateListener()
分配给您的mAuth
字段,然后在您想要的任何地方使用它。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.