You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 07:27:54