我应该将注册按钮放在片段中的什么位置(异步数据库对 Firebase 实时数据库的调用太慢会导致应用崩溃)



我发誓我搜索了很多,但最终我要投降,我要问。我正在制作一个只有一个活动的应用程序,一切都通过片段进行管理,一切正常,布局设置良好,但我的注册有问题。

我有3种类型的注册,邮件和密码,Facebook和谷歌。 电子邮件注册方法:

private void emailSignUp() {
String email = etEmail.getText().toString();
String password = etPassword.getText().toString();
if(email.isEmpty()||password.isEmpty()) {
Toast.makeText(getActivity(), "Empty fields are not allowed.",
Toast.LENGTH_SHORT).show();
return;
}
mAuth.createUserWithEmailAndPassword(email, password)
.addOnCompleteListener(getActivity(), 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, "signInWithCredential:success");
user = mAuth.getCurrentUser();
//Read DB Score
database = FirebaseDatabase.getInstance();
database.getReference(user.getUid())
.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
if(!dataSnapshot.exists()) database.getReference(user.getUid()).setValue(0);
updateUI(user);
}
@Override
public void onCancelled(@NonNull DatabaseError databaseError) {
}
});
} else {
// If sign in fails, display a message to the user.
Log.w(TAG, "createUserWithEmail:failure", task.getException());
Toast.makeText(getActivity(), "Authentication failed.",
Toast.LENGTH_SHORT).show();
}
}
});
}

其他 2 个是相同的;这些方法是通过使用 onClickListener 从onActivityCreated调用的,该方法可以正常工作。

如您所见,这些方法中的每个方法都使用刚刚创建的用户的 UID 创建一个数据库值,并将其设置为 0。到目前为止,一切都很完美。 有一个 updateUI 方法负责移动片段,如果用户不为 null,下一个片段是一个仪表板,这里我在从服务器获取数据时遇到问题: 每次我注册一个新用户时,当我调用 db 时,我都会得到一个 null 对象引用,因为先例片段中 db 键的异步创建仍未完成,如果我重新启动应用程序,仪表板片段会完美运行,因为值在那里。

在仪表板片段中,我正在从onStart获取数据库数据。

我几乎完全确定我的代码中的错误是在仪表板片段中放置按钮调用或 fetchData,我试图理解片段生命周期,但如果调用异步任务,则无法理解它。

有什么帮助吗?

PS:每个对象或值在片段代码中都设置为私有。

根据要求,错误:

2019-11-25 20:16:04.403 3342-3342/com.d136.uselessrank E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.d136.uselessrank, PID: 3342
java.lang.NullPointerException: Attempt to invoke virtual method 'boolean java.lang.String.isEmpty()' on a null object reference
at com.d136.uselessrank.fragments.fragmentDashboard.getName(fragmentDashboard.java:142)
at com.d136.uselessrank.fragments.fragmentDashboard.onStart(fragmentDashboard.java:67)
at androidx.fragment.app.Fragment.performStart(Fragment.java:2632)
at androidx.fragment.app.FragmentManagerImpl.moveToState(FragmentManagerImpl.java:915)
at androidx.fragment.app.FragmentManagerImpl.moveFragmentToExpectedState(FragmentManagerImpl.java:1238)
at androidx.fragment.app.FragmentManagerImpl.moveToState(FragmentManagerImpl.java:1303)
at androidx.fragment.app.BackStackRecord.executeOps(BackStackRecord.java:439)
at androidx.fragment.app.FragmentManagerImpl.executeOps(FragmentManagerImpl.java:2079)
at androidx.fragment.app.FragmentManagerImpl.executeOpsTogether(FragmentManagerImpl.java:1869)
at androidx.fragment.app.FragmentManagerImpl.removeRedundantOperationsAndExecute(FragmentManagerImpl.java:1824)
at androidx.fragment.app.FragmentManagerImpl.execPendingActions(FragmentManagerImpl.java:1727)
at androidx.fragment.app.FragmentManagerImpl$2.run(FragmentManagerImpl.java:150)
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)

和片段仪表板:

private void getName() {
if(currentUser.getDisplayName().isEmpty()) email.setText(currentUser.getEmail());
else email.setText(currentUser.getDisplayName());
}

从同一个 FragmentDashboard 调用:

@Override
public void onStart() {
super.onStart();
getName();
getProfileImage();
readScore();
}

当前用户它肯定是空的,问题是当调用当前用户(OnActivityCreated(时,片段仍未完成填充该数据库值。我如何让它等待它?

多亏了@Frank van Puffelen,在我实现的片段仪表板中:

@Override
public void onStart() {
super.onStart();
FirebaseAuth.getInstance().addAuthStateListener(new FirebaseAuth.AuthStateListener() {
@Override
public void onAuthStateChanged(@NonNull FirebaseAuth firebaseAuth) {
mAuth = FirebaseAuth.getInstance();
currentUser = mAuth.getCurrentUser();
updateUI(currentUser);
}
});
}

经过一番调试,一切顺利。

创建新用户时,将正确填充AuthResult中的用户对象。但是,FirebaseAuth.getInstance().getCurrentUser()是异步填充的。

通常这不是问题,但是如果您过渡到新的活动/片段,则还不能依赖正在填充FirebaseAuth.getInstance().getCurrentUser()

您在这里有两个选择:

  1. authResult.getUser()的值放在共享首选项中,并在下一个活动/片段中作为当前用户使用它。
  2. 下一个活动/片段中附加带有FirebaseAuth.getInstance().addAuthStateListener(listener)的身份验证状态侦听器,并等待用户在那里初始化。

    FirebaseAuth.getInstance().addAuthStateListener(new  FirebaseAuth.AuthStateListener() {
    @Override
    public void onAuthStateChanged(@NonNull FirebaseAuth firebaseAuth) {
    FirebaseUser user = firebaseAuth.getCurrentUser();
    if (user != null) {
    // User is signed in
    Log.d(TAG, "onAuthStateChanged:signed_in:" + user.getUid());
    } else {
    // User is signed out
    Log.d(TAG, "onAuthStateChanged:signed_out");
    }
    // ...
    }
    });
    

相关内容

  • 没有找到相关文章

最新更新