【问题标题】:Waiting for Firebase Auth to finish and then load the data to fragment等待 Firebase Auth 完成,然后将数据加载到片段
【发布时间】:2021-05-04 11:45:18
【问题描述】:

我正在使用 Firebase 身份验证,并且我已经(连同 UI)实现了一个身份验证系统来登录和注册我的用户。

在我的第一个片段中,我有一个回收器视图,它从 firestore 数据库加载一些数据,执行需要来自当前用户 (ID) 的数据的查询,并且由于某种原因它在主要活动之前加载,因此它每次都崩溃时间,因为用户为空。

在 Fragment 类的 onCreateView 内部,我尝试了一个 if-else 条件,如果它为 null,则强制用户登录,并且不会调用加载数据的方法,但在我登录后,该方法只会再次手动重新加载片段时(更改片段时)调用,因此显示的数据不准确。

有什么办法可以改变这一点,让片段等到注册完成?

(调用方法loadAllHousesId时代码崩溃)

错误:

java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String com.google.firebase.auth.FirebaseUser.getUid()' on a null object reference
        at cat.itb.studenthousing.fragments.LandingPage.loadAllHousesId(LandingPage.java:61)

我的代码:

主活动:

public class MainActivity extends AppCompatActivity {

    BottomNavigationView bottomNavigationView;

    public static FirebaseAuth firebaseAuth;
    FirebaseAuth.AuthStateListener mAuthListener;

    List<AuthUI.IdpConfig> provider = Arrays.asList(
            new AuthUI.IdpConfig.GoogleBuilder().build(),
            new AuthUI.IdpConfig.EmailBuilder().build(),
            new AuthUI.IdpConfig.PhoneBuilder().build(),
            new AuthUI.IdpConfig.AnonymousBuilder().build()

    );


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

    

        firebaseAuth = FirebaseAuth.getInstance();
        mAuthListener = new FirebaseAuth.AuthStateListener() {
            @Override
            public void onAuthStateChanged(@NonNull FirebaseAuth firebaseAuth) {
                FirebaseUser user = firebaseAuth.getCurrentUser();


                if (user == null) {
                    
                    startActivity(AuthUI.getInstance()
                            .createSignInIntentBuilder()
                            .setAvailableProviders(provider)
                            .setIsSmartLockEnabled(false)
                            .build());

                } 
            }
        };


        bottomNavigationView = findViewById(R.id.bottom_navigation_main);

        NavHostFragment navHostFragment =
                (NavHostFragment) getSupportFragmentManager().findFragmentById(R.id.navHostFragment);
        NavController navController = navHostFragment.getNavController();

        NavigationUI.setupWithNavController(bottomNavigationView, navController);



    }


    @Override
    public void onResume() {
        super.onResume();
        firebaseAuth.addAuthStateListener(mAuthListener);
    }

    @Override
    public void onPause() {
        super.onPause();
        firebaseAuth.removeAuthStateListener(mAuthListener);
    }


}

片段:

public class LandingPage extends Fragment {

    public static FirebaseFirestore db;
    private RecyclerView mRecyclerView;
    private EditText maxPrice, minPrice;
    private Spinner areaSpinner;
    private Button searchButton;
    String area, minValue, maxValue;

    //this var will store all the houses that the user has already applied for
    private List<String> housesId;

    ArrayList<House> houseArrayList;

    AvailableHousesRecyclerViewAdapter adapter;


    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);


    }


    public void loadAllHousesId() {


        db.collection("applications")
                .whereEqualTo("studentId", firebaseAuth.getCurrentUser().getUid())
                .get()
                .addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
                    @Override
                    public void onComplete(@NonNull Task<QuerySnapshot> task) {
                        for (DocumentSnapshot document : task.getResult()) {
                            housesId.add(document.getString("houseId"));
                        }
                    }
                });

    }




    private void setUpFirebase() {
        db = FirebaseFirestore.getInstance();
    }

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View v = inflater.inflate(R.layout.landing_page, container, false);


        housesId = new ArrayList<>();
        houseArrayList = new ArrayList<>();


        mRecyclerView = v.findViewById(R.id.recyclerViewHouses);
        mRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
        mRecyclerView.setHasFixedSize(true);

        
        setUpFirebase();
        //here is where my code crash
        loadAllHousesId();
        loadAllAvailableHousesFromFirebase();



        return v;
    }


}

【问题讨论】:

  • 如果您遇到问题,最好在发布问题时创建MCVE。您为此问题发布了近 500(五百)行行代码。人们要解析和尝试在线调试的内容很多。请编辑您的问题并隔离问题,这样可以增加获得帮助的机会。
  • 我刚刚编辑了问题并删除了一些未使用的方法,谢谢指出!
  • 如果应用程序崩溃,会有一个堆栈跟踪。请在 logcat 上查找,并将其添加到您的问题中。

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


【解决方案1】:

简单地说,您尝试在它完成初始化之前调用FirebaseAuth.getCurrentUser(),它在初始活动/视图创建阶段永远不会初始化。

您需要做的是等待onAuthStateChanged 使用有效的登录用户至少触发一次,然后在用户未登录时加载房屋数据或具有后备值。

用最简单的形式替换

//here is where my code crash
loadAllHousesId();
loadAllAvailableHousesFromFirebase();

firebaseAuth = FirebaseAuth.getInstance();
mAuthListener = new FirebaseAuth.AuthStateListener() {
    @Override
    public void onAuthStateChanged(@NonNull FirebaseAuth firebaseAuth) {
        FirebaseUser user = firebaseAuth.getCurrentUser();

        if (user != null) {
            loadAllHousesId();
            loadAllAvailableHousesFromFirebase();
        } else {
            clearAllHouses()
        }
    }
};
firebaseAuth.addAuthStateListener(mAuthListener)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多