如何从实时数据中删除观察者,以便在导航回片段时不会显示两次

问题描述 投票:3回答:3

我有一个片段,当用户成功登录时会显示一个弹出窗口。如果我导航到一个新的片段并返回,则会再次显示带有先前用户名的弹出窗口。我使用SingleLiveEvent解决了此问题,但现在我必须重构代码以使用MediatorLiveData,因为我的数据可以来自2个来源(远程和数据库),并且与SingleLiveEvent不兼容。

我曾尝试使用事件包装器并删除onDestroyView()上的观察者,但到目前为止没有任何效果,当我移回到该片段时,livedata onChanged函数不断被调用。这是我的一些片段:

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    // Inflate the layout for this fragment
    binding = FragmentDashboardBinding.inflate(inflater, container, false);
    binding.setLifecycleOwner(getActivity());

    //Get the attendanceViewModel for registering attendance
    attendanceViewModel = ViewModelProviders.of(this).get(AttendanceViewModel.class);
    attendanceViewModel.getAttendance().observe(getViewLifecycleOwner(), attendanceAndMember -> {
        if (attendanceAndMember != null && attendanceAndMember instanceof AttendanceMemberModel) {
            clokedInOutMember = attendanceAndMember.member;
        }
        showResultClockInOutPopup();
    });

    return binding.getRoot();
}

private void showResultClockInOutPopup() {

    clockInBuilder = new AlertDialog.Builder(getActivity());

    View view = getLayoutInflater().inflate(R.layout.status_clock_in_out_popup, null);
    TextView responseClockInOut = view.findViewById(R.id.responseClockInOut);
    Button dismissButton = view.findViewById(R.id.dismissButton);

    //Setup Popup Text
    if (clokedInOutMember != null) {
        if (StringToBool(clokedInOutMember.is_clocked_in_temp)) {
            responseClockInOut.setText("Bienvenue " + clokedInOutMember.name + ", tu es bien enregistré(e).");
        } else {
            responseClockInOut.setText("Désolé de te voir partir " + clokedInOutMember.name + ", à bientôt!");
        }
    } else {
        responseClockInOut.setText("Oups, il semblerait qu'il y ait une erreur...\n Essaye à nouveau.");
    }

    [..SETUP ALERTDIALOG...]

        //Dismiss popup
        dismissButton.setOnClickListener(v -> {
            clockInResultDialog.dismiss();
            clockInResultPopupShowed = false;
            clokedInOutMember = null;
        });

        clockInResultDialog.show();
        clockInResultPopupShowed = true;
    }

}

@Override
public void onDestroyView() {
    attendanceViewModel.getAttendance().removeObservers(this);
    super.onDestroyView();
}

这是我的ViewModel,当我从片段中获取userId时,我必须使用转换,然后传递给Viewmodel,然后将其传递给存储库以进行查询(也许有更好的方法了?):

public class AttendanceViewModel extends AndroidViewModel {

private AttendanceRepository repository = AttendanceRepository.getInstance();
public LiveData<AttendanceMemberModel> mAttendanceAndMember;
private MutableLiveData<String> mId =  new MutableLiveData<>();

private MediatorLiveData<AttendanceMemberModel> mObservableAttendance = new MediatorLiveData<AttendanceMemberModel>();
{
    mObservableAttendance.setValue(null);

    mAttendanceAndMember = Transformations.switchMap(mId, id -> {
        return repository.saveAttendance(id);
    });

    mObservableAttendance.addSource(mAttendanceAndMember, mObservableAttendance::setValue);
}


public AttendanceViewModel(@NonNull Application application) {
    super(application);
}

public LiveData<AttendanceMemberModel> getAttendance() {
    return mObservableAttendance;

}

public void setMemberId(String id) {
    mId.setValue(id);
}


@Override
protected void onCleared() {
    mObservableAttendance.setValue(null);
    super.onCleared();
}
}
java android android-livedata mediatorlivedata
3个回答
0
投票

请使用其中任何一个,根据您的需要工作和表现。

@Override
public void onPause() {
    attendanceViewModel.getAttendance().removeObservers(this);
    super.onPause();
}

@Override
public void onStop() {
    attendanceViewModel.getAttendance().removeObservers(this);
    super.onStop();
}

Fragment Life Cycle

看看片段的生命周期,它将带给您更多的想法。让我知道这是否可行。


0
投票

最好的方法是将视图模型绑定到OnViewCreated Meathod。

    @Override
    public void onActivityCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        attendanceViewModel = ViewModelProviders.of(this).get(AttendanceViewModel.class);
        setUpObservers();
      }



    private void setUpObservers() {
        attendanceViewModel.getAttendance().observe(getViewLifecycleOwner(), attendanceAndMember -> {
        if (attendanceAndMember != null && attendanceAndMember instanceof AttendanceMemberModel) {
            clokedInOutMember = attendanceAndMember.member;
        }
        showResultClockInOutPopup();
    });
    }

如果仍然无法正常工作,请告诉我。谢谢。


0
投票

我可以建议您两种方式。首先创建一个boolean变量,是否在Fragment中显示对话框,并在显示对话框后将其设置为true,然后在显示对话框之前检查是否显示了对话框。第二种方法是在显示对话框之后,将livedata值设置为null,然后在显示对话框之前检查观察者值是否为null。我更喜欢第二种方式。

© www.soinside.com 2019 - 2024. All rights reserved.