方向更改后无法在 Firebase 任务执行时到达重新创建的 activity

Can't reach the recreated activity on Firebase task execution after orientation change

我在我的应用程序中使用了一些 Firebase 任务,当它正在执行任务时,我想显示一个加载对话框,该对话框无法通过点击外部或按返回等方式取消,并且会在结束时关闭的任务。例如;

FragmentManager fm = getSupportFragmentManager();
LoadingDialog ld = new LoadingDialog();
ld.show(fm, "dialog");

storageReference.getDownloadUrl().addOnSuccessListener(uri -> {
    Fragment dialog = fm.findFragmentByTag("dialog");
    if (dialog != null) {
        LoadingDialog ld = (LoadingDialog) dialog;
        ld.dismiss();
    }
});

当方向状态固定时,它按预期工作,但当方向在过程中发生变化时 fm.findFragmentByTag("dialog"); returns 任务完成后为空。

我的 LoadingDialog class 扩展了 DialogFragment;

@NonNull
@Override
public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
    Activity activity = getActivity();
    assert activity != null;
    AlertDialog.Builder builder =
            new AlertDialog.Builder(activity, R.style.LoadingDialog);

    LayoutInflater inflater = activity.getLayoutInflater();
    View view = inflater.inflate(R.layout.dialog_loading, null);
    builder.setView(view);
    setCancelable(false);

    return builder.create();
}


@Override
public void show(FragmentManager manager, String tag) {
    FragmentTransaction ft = manager.beginTransaction();
    ft.add(this, tag);
    ft.commitAllowingStateLoss();
}

为什么我无法使用其标签找到我的对话片段?

编辑: 我找到了原因,由于 activity 重新创建,我无法访问我的对话框片段。我执行任务的旧 activity 被销毁,它试图从被销毁的 activity.

访问片段管理器

感谢@Bö macht Blau,我实现了我的 ViewModel class 并通过使用 MutableLiveData 对象将一些信息传递到我的 activity 我观察 Firebase 执行的地方任务。 java;

的一些示例代码
public class AuthViewModel extends AndroidViewModel {
    public MutableLiveData<LoginInfo> loginInfoLiveData;

    public AuthViewModel(@NonNull Application application) {
        super(application);
        loginInfoLiveData = new MutableLiveData<>();
    }

    public void signIn(String email, String password) {
        FirebaseAuth auth = FirebaseAuth.getInstance();
        auth.signInWithEmailAndPassword(email, password)
                .addOnCompleteListener(task -> {
                    FirebaseUser firebaseUser;
                    firebaseUser = auth.getCurrentUser();
                    LoginInfo loginInfo = new LoginInfo(
                            task.isSuccessful(),
                            firebaseUser != null && firebaseUser.isEmailVerified(),
                            task.getException());
                    loginInfoLiveData.postValue(loginInfo);
                });
    }
}

在 activity 的 onCreate 方法;

authViewModel = new ViewModelProvider(this,
        ViewModelProvider.AndroidViewModelFactory.getInstance(getApplication()))
        .get(AuthViewModel.class);

authViewModel.loginInfoLiveData.observe(this, loginInfo -> {
    hideLoadingDialog();
    if (loginInfo.isSuccessful()) {
        if (loginInfo.isEmailVerified()) {
            startActivity(new Intent(context, MainActivity.class));
            finish();
        } else {
            auth.signOut();
            toast(R.string.verification_error);
        }
    } else {
        handleException(loginInfo.getException());
    }
});

您可以将与 Firebase 任务相关的代码移至 ViewModel(甚至移至将 LiveData 对象公开给 ViewModel 的存储库)。任务成功完成后,ViewModel 可以通过调用

更新 MutableLiveData<Boolean> _loadingSuccess
 _loadingSuccess.postValue(true)

ViewModel 反过来可以暴露一个 LiveData<Boolean> loadingSuccess = _loadingSuccess,您的 FragmentActivity 可以观察到。

由于 ViewModel 将在配置更改后继续存在,因此 FragmentActivity 可以在每次到达前台时重新注册观察者

Fragment

的代码示例
override fun onActivityCreated(savedInstanceState: Bundle?) {
    super.onActivityCreated(savedInstanceState)
    viewModel.loadingSuccess.observe(viewLifecycleOwner) { success ->
        run {
            if(success != null){
                dismissLoadingDialog()
            }
        }
    }
}

有关 LiveData 和 Viewmodel 的更多信息,请参阅 Guide to app architecture