Как вернуть ссылку на документ вновь созданного документа из репозитория в ViewModel на Java?

Вопрос или проблема

Когда я создаю новый документ в репозитории с помощью database.collection("Groups").document(id).set(group) и пытаюсь вернуть ссылку на документ, выполняя database.collection("Groups").document(id), ссылаясь на только что созданный документ, я не могу получить документ, так как Firebase Firestore работает асинхронно, и .set все еще добавляет новый документ, в результате чего я непреднамеренно возвращаю ссылку на документ до его создания.

Что я пробовал

  • Возврат LiveData из репозитория, но это не задача репозитория
  • Добавление LiveData в ViewModel, но ViewModel не должна изменять базу данных (добавляя новый документ в Firestore)
  • Смотрел про Task.await, но это блокирует главный поток

Я ожидаю возврата DocumentReference из репозитория в ViewModel, чтобы я мог опубликовать его значение в моем MutableLiveData в ViewModel

Ответ или решение

Для того чтобы вернуть ссылку на документ, который был только что создан в репозитории, обратно в ViewModel, можно использовать подход с вызовом обратного метода (callback) или использовать CompletableFuture для работы с асинхронностью. Это упростит взаимодействие между репозиторием и ViewModel, не блокируя основной поток. Приведу пример на Java с использованием Firebase Firestore.

Шаги:

  1. Создайте интерфейс обратного вызова:
    Этот интерфейс будет содержать метод, который будет вызываться после завершения операции по созданию документа.

    public interface DocumentCallback {
       void onDocumentCreated(DocumentReference documentReference);
       void onError(Exception e);
    }
  2. Обновите репозиторий:
    Измените метод создания документа так, чтобы он принимал интерфейс обратного вызова. После завершения операции сохранения вызывайте метод обратного вызова.

    public class GroupRepository {
       private FirebaseFirestore database;
    
       public GroupRepository() {
           database = FirebaseFirestore.getInstance();
       }
    
       public void createGroup(String id, Group group, DocumentCallback callback) {
           database.collection("Groups").document(id).set(group)
               .addOnSuccessListener(aVoid -> {
                   DocumentReference documentReference = database.collection("Groups").document(id);
                   callback.onDocumentCreated(documentReference);
               })
               .addOnFailureListener(e -> callback.onError(e));
       }
    }
  3. Вызовите метод из ViewModel:
    После обновления репозитория, вы можете вызывать данный метод из ViewModel и обрабатывать ссылку на документ, используя реализацию интерфейса обратного вызова.

    public class GroupViewModel extends ViewModel {
       private GroupRepository groupRepository;
       private MutableLiveData<DocumentReference> documentReferenceLiveData = new MutableLiveData<>();
    
       public GroupViewModel() {
           groupRepository = new GroupRepository();
       }
    
       public LiveData<DocumentReference> getDocumentReference() {
           return documentReferenceLiveData;
       }
    
       public void addGroup(String id, Group group) {
           groupRepository.createGroup(id, group, new DocumentCallback() {
               @Override
               public void onDocumentCreated(DocumentReference documentReference) {
                   documentReferenceLiveData.postValue(documentReference);
               }
    
               @Override
               public void onError(Exception e) {
                   // Обработка ошибки по мере необходимости
               }
           });
       }
    }

Заключение

Используя данную архитектуру с интерфейсом обратного вызова, вы избегаете блокировки главного потока и одновременно сохраняете чистоту кода, соответствуя принципам разделения ответственности между репозиторием и ViewModel. Это позволит вам эффективно передавать обратную связь о созданных документах и управлять состоянием пользовательского интерфейса.

Оцените материал
Добавить комментарий

Капча загружается...