Как мне обработать слишком раннее наблюдение LiveData, которое зависит от состояния аутентификации firebase, чтобы быть аутентифицированным? - PullRequest
0 голосов
/ 09 апреля 2020

В моем фрагменте onViewCreated у меня есть перенаправление, основанное на состоянии аутентификации, и я также связываю наблюдателей Frag, например:

class TodoMvvmFragment : Fragment() {
  private val loginViewModel by viewModel<LoginViewModel>()
  private val todoViewModel by viewModel<TodoViewModel>()
  val TAG = "TODO_FRAG"
  var rvAdapter:TodoListAdapter? = null
  var observersBound = false

   ///...omitted

 override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)

    rvAdapter = TodoListAdapter(todoViewModel, this )
    todo_rv.let {
        it.adapter = rvAdapter
        it.layoutManager = LinearLayoutManager(requireActivity())
    }

    loginViewModel.authenticationState.observe(this, Observer {
        when(it) {
                LoginViewModel.AuthenticationState.UNAUTHENTICATED -> {
                    findNavController().navigate(R.id.action_global_loginFragment)
                }
                LoginViewModel.AuthenticationState.AUTHENTICATED -> {
                    // Viewmodel calls aspects of the repository that rely on AUTHSTATE
                    // to be AUTHENTICATED, so don't bind observers until we are.
                    if (!observersBound) {
                        observersBound = true
                        todoViewModel.init()
                        bindObservers()
                        addListeners()
                    }

                }
                else -> {
                    Log.d(TAG, it.toString())
                }

        }
    })




}

Вот проблема c Наблюдатель:

  fun bindObservers() {
    todoViewModel.getFilteredTodos().observe(this, Observer{
        if (it.data == null) {
            handleException("Error with todos by timestamp query", it.exception)
        } else {
            val todos: List<Todo> = it.data.map { todoOrException ->
                if( todoOrException.data == null) {
                    handleException("error with individual Todo", todoOrException.exception)
                    null
                } else {
                    todoOrException.data
                }
            }.filterNotNull()

            rvAdapter?.submitList(todos)
        }
    })

Это просачивается вниз к репо, который создает запрос Firebase. Обратите внимание на .document (auth.uid.toString ()) ... если этот запрос создан до авторизации пользователя, данные не возвращаются.

fun allTodosQuery(): Query {
    return firestore.collection(PATH_ROOT)
        .document(PATH_APPDATA)
        .collection(PATH_USERS)
        .document(auth.uid.toString())
        .collection(PATH_TODOS)
        .orderBy(FIELD_TIMESTAMP, Query.Direction.DESCENDING)

Вернувшись в прослушиватель состояния аутентификации, я привязка наблюдателей ТОЛЬКО при изменении состояния аутентификации на аутентифицированное. Я также защищаю это с помощью логического значения, так что это происходит только один раз. Когда я этого не делаю и просто привязываю наблюдателей в onViewCreated после прослушивателя состояния авторизации, я не получаю никаких данных о начальной загрузке приложения.

Мой вопрос заключается в том, как сохранить данные, которые зависят от аутентификации authstate, от того, что они ничего не пропускают, когда они связаны до аутентификации пользователя. По сути, как мне избежать получения неверного запроса с нулевым auth.uid из репозитория до того, как пользователь будет аутентифицирован?

1 Ответ

0 голосов
/ 09 апреля 2020

Спасибо, что разрешили мне резиновую утку. Вот решение:

var _queryResult = Transformations.switchMap(_authState){
    if (_authState.value == LoginViewModel.AuthenticationState.AUTHENTICATED) {
        repo.getAllTodosByTimestamp()
    } else {
        MutableLiveData<ListOrException<TodoOrException>>()
    }
}

Таким образом, мы не создаем и не запускаем запрос (в репо) до его аутентификации.

...