Не удается достичь воссозданного действия при выполнении задачи Firebase после изменения ориентации - PullRequest
1 голос
/ 31 марта 2020

Я использую некоторые задачи Firebase в своем приложении, и пока оно выполняет задачу, я хочу отобразить диалоговое окно загрузки, которое нельзя отменить, нажав снаружи или нажав назад и т. Д. c. и будет уволен в конце задания. Например;

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"); возвращает ноль после завершения задачи.

Мой класс LoadingDialog, расширяющий 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();
}

Почему я не могу найти свой фрагмент диалога, используя его тег?

Редактировать: Я нашел причину этого, я не могу добраться до своего фрагмента диалога из-за активного отдыха. Старое действие, которое я выполнил, было уничтожено, и оно пытается получить доступ к диспетчеру фрагментов из уничтоженного действия.

Благодаря @ Bö macht Blau я реализовал свой класс ViewModel и передал некоторую информацию с помощью MutableLiveData возражает против моей деятельности, где я наблюдаю за выполнением задач 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);
                });
    }
}

при 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());
    }
});

1 Ответ

1 голос
/ 31 марта 2020

Вы можете переместить код, связанный с задачами Firebase, в ViewModel (или даже в репозиторий, который выставляет LiveData объекты в ViewModel). Как только задача успешно завершена, ViewModel может обновить MutableLiveData<Boolean> _loadingSuccess, вызвав

 _loadingSuccess.postValue(true)

ViewModel, в свою очередь, может выставить LiveData<Boolean> loadingSuccess = _loadingSuccess, который ваш Fragment или Activity может наблюдать.

Поскольку ViewModel переживет изменение конфигурации, Fragment или Activity может перерегистрировать наблюдателя каждый раз, когда он выходит на передний план

Пример кода для Fragment

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

Для получения дополнительной информации о LiveData и Viewmodels см. Руководство по архитектуре приложения

...