Android App迁移Firestore后更新用户数据时应用崩溃问题求助
问题定位与解决方案
从你的错误日志能直接揪出问题根源:当你在编辑页面保存数据后,Firestore数据更新触发了UserProfileFragment里的快照监听器,但此时UserProfileFragment的视图已经被销毁,调用getView()返回了null,进而调用findViewById时抛出空指针异常。
为什么会出现这个问题?
当你点击“编辑资料”跳转到EditUserProfileFragment时,UserProfileFragment的onDestroyView方法会被触发,它的视图(View)已经被销毁,但你之前在displayFirestoreData里注册的Firestore快照监听器并没有被移除。当你保存编辑后Firestore数据更新,监听器的onEvent方法依然会被调用,这时候getView()已经是null,自然就崩溃了。
具体修复步骤
1. 保存监听器引用,视图销毁时移除监听
修改UserProfileFragment的代码,把快照监听器的引用保存下来,在视图销毁时主动取消监听,同时在回调里先检查视图是否存在:
public class UserProfileFragment extends Fragment implements View.OnClickListener { private Button btnEditProfile; private FirebaseFirestore db = FirebaseFirestore.getInstance(); private DocumentReference usersDocRef = db.collection("Users").document(FirebaseAuth.getInstance().getCurrentUser().getDisplayName()); // 新增:保存监听器引用,方便后续移除 private ListenerRegistration listenerRegistration; @Override public void onViewCreated(View view, Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); displayFirestoreData(); btnEditProfile = (Button) view.findViewById(R.id.edit_user_info); btnEditProfile.setOnClickListener(this); } @Nullable @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { return inflater.inflate(R.layout.fragment_user_profile, container, false); } @Override public void onClick(View v) { Fragment fragment = null; if (v.getId() == R.id.edit_user_info) { fragment = new EditUserProfileFragment(); } if (fragment != null) { getActivity().getSupportFragmentManager().beginTransaction() .replace(R.id.fragment_container, fragment) .addToBackStack(null) .commit(); } } public void displayFirestoreData() { // 保存监听器引用 listenerRegistration = usersDocRef.addSnapshotListener(this.getActivity(), new EventListener<DocumentSnapshot>() { @Override public void onEvent(DocumentSnapshot documentSnapshot, FirebaseFirestoreException e) { // 新增:先检查视图是否存在,避免空指针 if (getView() == null) { return; } if (documentSnapshot.exists()) { String name = documentSnapshot.getString(FULLNAME); String email = documentSnapshot.getString(EMAIL); String nickname = documentSnapshot.getString(NICKNAME); String age = documentSnapshot.getString(AGE); String nationality = documentSnapshot.getString(NATIONALITY); String status = documentSnapshot.getString(STATUS); TextView txtProfileName = (TextView) getView().findViewById(R.id.profile_section_fullname); txtProfileName.setText(name); TextView txtProfileEmail = (TextView) getView().findViewById(R.id.profile_section_email); txtProfileEmail.setText(email); TextView txtProfileNickname = (TextView) getView().findViewById(R.id.profile_section_nickname); txtProfileNickname.setText(nickname); TextView txtProfileAge = (TextView) getView().findViewById(R.id.profile_section_age); txtProfileAge.setText(age); TextView txtProfileNationality = (TextView) getView().findViewById(R.id.profile_section_nationality); txtProfileNationality.setText(nationality); TextView txtProfileStatus = (TextView) getView().findViewById(R.id.profile_section_status); txtProfileStatus.setText(status); } else if (e != null) { Log.w(TAG, "An exception occured", e); } } }); } // 新增:视图销毁时移除监听器,防止无效回调 @Override public void onDestroyView() { super.onDestroyView(); if (listenerRegistration != null) { listenerRegistration.remove(); } } }
2. 额外优化:完善现有功能逻辑
除了修复崩溃,还有两个小问题可以顺便完善:
- User类的文档存在判断逻辑无效:原
checkFireStoreDatabase里的if (usersDocRef != null)永远为true,应该通过get()方法判断文档是否存在:
protected void checkFireStoreDatabase() { FirebaseFirestore db = FirebaseFirestore.getInstance(); DocumentReference usersDocRef = db.collection("Users").document(userFullName); usersDocRef.get().addOnCompleteListener(task -> { if (task.isSuccessful()) { DocumentSnapshot document = task.getResult(); if (!document.exists()) { createNewEntry(); } } else { Log.d(TAG, "Error getting document: ", task.getException()); } }); }
- EditUserProfileFragment未处理年龄和国籍更新:原方法只更新了昵称,补上年龄和国籍的更新逻辑,同时保存后返回上一页:
public void updateFireStoreData(String nicknameUpdate, String ageUpdate, String nationalityUpdate) { FirebaseFirestore db = FirebaseFirestore.getInstance(); FirebaseUser currUser = FirebaseAuth.getInstance().getCurrentUser(); DocumentReference userDocRef = db.collection("Users").document(currUser.getDisplayName()); Map<String, Object> dataUpdate = new HashMap<>(); if (!nicknameUpdate.matches("")) { dataUpdate.put(NICKNAME, nicknameUpdate); } if (!ageUpdate.matches("")) { dataUpdate.put(AGE, ageUpdate); } if (!nationalityUpdate.matches("")) { dataUpdate.put(NATIONALITY, nationalityUpdate); } if (!dataUpdate.isEmpty()) { userDocRef.set(dataUpdate, SetOptions.merge()) .addOnSuccessListener(aVoid -> Log.d(TAG, "Document has been saved")) .addOnFailureListener(e -> Log.d(TAG, "Document could not be saved", e)); } // 保存后返回个人资料页面 getActivity().getSupportFragmentManager().popBackStack(); }
这样修改后,不仅能彻底解决崩溃问题,还能完善功能的完整性。
内容的提问来源于stack exchange,提问作者Vr33ni
相关产品推荐
相关产品推荐

