чтение документов Firestore с AsyncTask - PullRequest
2 голосов
/ 04 октября 2019

У меня есть база данных в Cloud Firestore, где у каждого документа есть определенный ключ «последнее обновление» со значением String, представляющий дату в форме YYYY-MM-DD. Каждый раз, когда документ обновляется, значение «последнего обновления» устанавливается как дата обновления.

Теперь я хочу, чтобы в моей деятельности был метод проверки документов на предмет их последнего обновления. Поскольку документы содержат довольно большие списки объектов, эта проверка обновлений занимает несколько секунд. Поэтому я решил отложить его до AsyncTask. Метод doInBackground в AsyncTask должен создать для документа DocumentReference noteRef и прочитать его «последнее обновление» с помощью noteRef.get (), снабженного слушателями onSuccess- и onFailure, в строку, которая затем возвращается методом.

Чтобы проверить это, я создал игрушечное действие MyTestActivity, которое вызывает вышеуказанный AsyncTask со строковыми аргументами «myCollection» и «myDocument» и отображает значение последнего обновления этого документа в TextView. Теперь вместо отображения фактического значения «2019-10-03» TextView отображает значение «1970-01-01», которое используется в doInBackground для инициализации возвращаемой переменной String. Это как если бы doInBackground не удосужился дождаться, пока документ не будет прочитан. Код выглядит следующим образом.

public class MyTestActivity extends AppCompatActivity{ 


    private Button button;
    private TextView textView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_my_test);

        button = findViewById(R.id.update_button);
        textView = findViewById(R.id.update_text_view);


    }


    public void buttonClicked(View view) throws ExecutionException, InterruptedException {

        UpdateTask task = new UpdateTask(this, "myCollection", "myDocument");
        String date =  task.execute().get();
        textView.setText("Last update on "+date);

    }


    private static class UpdateTask extends AsyncTask<Integer, Integer, String> {
        private WeakReference<MyTestActivity> activityWeakReference;
        String collection;
        String document;
        String lastUpdate;

        UpdateTask(MyTestActivity activity, String collection, String document) {
            activityWeakReference = new WeakReference<MyTestActivity>(activity);
            this.collection = collection;
            this.document = document;
            lastUpdate = new String();
        }

        @Override
        protected void onPreExecute() {
            super.onPreExecute();

            MyTestActivity activity = activityWeakReference.get();
            if (activity == null || activity.isFinishing()) {
                return;
            }

        }

        @Override
        protected String doInBackground(Integer... params) {
            FirebaseFirestore db = FirebaseFirestore.getInstance();
            DocumentReference noteRef = db.collection(collection).document(document);
            lastUpdate = "1970-01-01";


            noteRef.get()
                    .addOnSuccessListener(new OnSuccessListener<DocumentSnapshot>() {
                        @Override
                        public void onSuccess(DocumentSnapshot documentSnapshot) {
                            if (documentSnapshot.exists()) {
                                Map<String, Object> map = documentSnapshot.getData();
                                lastUpdate = (String)map.get("last update");
                                activityWeakReference.get().textView.setText(lastUpdate);

                            } else {
                                lastUpdate = "Document doesn't exist";


                            }
                        }
                    })
                    .addOnFailureListener(new OnFailureListener() {
                        @Override
                        public void onFailure(@NonNull Exception e) {
                            lastUpdate = "Listener failed.";

                        }
                    });



            return lastUpdate;


        }
    }
}

Кто-нибудь может объяснить, что здесь происходит?

Ответы [ 2 ]

2 голосов
/ 04 октября 2019

У меня есть база данных в Firebase Firestore, где у каждого документа есть определенный ключ «последнее обновление» со значением String, представляющий дату в виде ГГГГ-ММ-ДД.

Редко хранить дату в виде строки, вместо этого вы должны хранить ее как:

FieldValue.serverTimestamp()

Как объяснено в моем ответе из следующего поста:

Поэтому я решил отложить его до AsyncTask.

Клиент базы данных Cloud Firestore, уже запускает всесетевые операции в фоновом потоке. Это означает, что все операции выполняются без блокировки вашего основного потока. Добавление его в AsyncTask вообще не дает никаких преимуществ.

Теперь вместо отображения фактического значения «2019-10-03» TextView отображает значение «1970-01-01 ", который используется в doInBackground

Это происходит потому, что вы пытаетесь вернуть сообщение синхронно от асинхронного метода. Это не очень хорошая идея. Вы должны обрабатывать API-интерфейсы асинхронно, как и предполагалось.

Быстрое решение этой проблемы - использование значения lastUpdate только внутри метода onSuccess(), в противном случае я рекомендую вам просмотреть последнюю часть моего ответа отэто сообщение , в котором я объяснил, как это можно сделать с помощью пользовательского обратного вызова. Вы также можете взглянуть на это видео для лучшего понимания.

0 голосов
/ 04 октября 2019

Ой! Это плохой дизайн. Вызовы Firestore являются асинхронными, поэтому вам не нужно помещать их в фоновый метод asyncTask. Кроме того, использование synctask не выполнит ваш код быстрее. Вам нужно «загрузить сообщение», пока ваш OnSuccessListener не запустится.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...