Поэтому я добавил ChildEventListener и ValueEventListener в AsyncTask. Изобразите таким образом, что основной поток пользовательского интерфейса не будет беспокоить. Приведенный ниже код отлично работает, но вопрос в том, что произойдет, когда я завершу работу слушателей в моем нижележащем методе exitFirebase()?

Когда AsyncTask запускается, он проходит через doInBackground() добавление слушателей FireBase, а затем проходит через onPostExecute() и, по-видимому, завершается, но слушатели поддерживают работу AsyncTask прямо ..

Что происходит, когда я завершаю слушателей?

   /**
     * Typically when user sign in or app start
     */
    public void userSigneIn() {
        // start listening
        asyncTaskUserAddressHistory().execute();
    }


    public AsyncTask asyncTaskUserAddressHistory() {
        AsyncTask task = new AsyncTask<Object, Object, Object>() {

            /**
             * The User history address child event listener.
             * This is only used when app first install or user wipe data
             */
            ChildEventListener userHistoryAddressChildEventListener = new ChildEventListener() {

                @Override
                public void onChildAdded(DataSnapshot snapshot, String prevKey) {
                    // do the work and continue listen
                }

                @Override
                public void onChildChanged(DataSnapshot snapshot, String prevKey) {
                }

                @Override
                public void onCancelled(DatabaseError error) {
                    // remove listener
                    ChildEventListener listener = mChildListenerMap.get(onCancel);
                    onCancel.removeEventListener(listener);
                    // start over
                    startListenForUserAddressHistory();
                }

                @Override
                public void onChildRemoved(DataSnapshot snapshot) {
                }

                @Override
                public void onChildMoved(DataSnapshot snapshot, String prevKey) {
                }
            };

            ValueEventListener userHistoryAddressvalueEventListener = new ValueEventListener() {
                @Override
                public void onDataChange(DataSnapshot dataSnapshot) {
                    // get history for current user
                    if (dataSnapshot.getChildrenCount() != 0) {
                        // do the work and start over
                        startListenForUserAddressHistory();
                    }
                }

                @Override
                public void onCancelled(DatabaseError databaseError) {
                    // remove listener
                    ValueEventListener listener = mValueListenerMap.get(onCancel);
                    onCancel.removeEventListener(listener);
                    // start over
                    startListenForUserAddressHistory();
                }
            };

            @Override
            protected Object doInBackground(Object... params) {
                // If local user don´t have any history start the ChildEventListener.
                if (HistoryManager.getInstance().getHistoryItems(mFireBaseAuth.getCurrentUser().getUid()).size() == 0) {
                    // Local cache of address history is empty get all address history for this user and start listen for new items
                    final Query query = ref.child(USER_HISTORY).limitToLast(LIMIT);
                    onCancel = query.getRef();
                    mChildListenerMap.put(query.getRef(), userHistoryAddressChildEventListener);
                    query.addChildEventListener(userHistoryAddressChildEventListener);

                } else {
                    // If client have history start the ValueEventListener.
                    // Typically this is not the first time app starts.
                    startListenForUserAddressHistory();
                }
                return null;
            }

            @Override
            protected void onPostExecute(Object o) {
                super.onPostExecute(o);
                // This runs and listeners are alive
            }

            /**
             * Start listen for nye entries based on that server have entries<br>
             * and client have entries, typically this is not the first time App starts.
             * This uses a ValueEventListener.
             */
            private void startListenForUserAddressHistory() {
                // Local history is not empty so we must go get only new items
                final HistoryItem historyItem = HistoryManager.getInstance()
                        .orderHistoryByDateAndGetNewest(mFireBaseAuth.getCurrentUser().getUid());
                final Query query = ref
                        .child(USER_HISTORY)
                        .child(mFireBaseAuth.getCurrentUser().getUid())
                        .child(UserHistory.ADDRESS_HISTORY)
                        .orderByKey()
                        .startAt(historyItem.getPushKey());
                mValueListenerMap.put(query.getRef(), userHistoryAddressvalueEventListener);
                skipStartAtKey = historyItem.getPushKey();
                onCancel = query.getRef();
                query.addValueEventListener(userHistoryAddressvalueEventListener);
            }
        };
        return task;
    }

    /**
     * App is closing or User has signed out
     * Called from both onClose() and userSignedOut()
     */
    private void exitFirebase() {
        if (userLogger != null)
            userLogger.log(USER_SIGNED_OUT);
        // Close ChildEventListener(s)
        for (Map.Entry<DatabaseReference, ChildEventListener> entry : mChildListenerMap.entrySet()) {
            DatabaseReference ref = entry.getKey();
            ChildEventListener listener = entry.getValue();
            if (listener != null && ref != null)
                ref.removeEventListener(listener);
        }
        // Close ValueEventListener(s)
        for (Map.Entry<DatabaseReference, ValueEventListener> entry : mValueListenerMap.entrySet()) {
            DatabaseReference ref = entry.getKey();
            ValueEventListener listener = entry.getValue();
            if (listener != null && ref != null)
                ref.removeEventListener(listener);
        }
        if (userAuthListener != null)
            mFireBaseAuth.removeAuthStateListener(userAuthListener);
        userLogger = null;
    }
1
Tord Larsen 24 Дек 2016 в 14:33

1 ответ

Лучший ответ

Поэтому я добавил ChildEventListener и ValueEventListener в AsyncTask.

Нет необходимости использовать AsyncTask для реализации операций Firebase. Firebase уже оптимизирована. Таким образом, вам не нужно использовать фоновый поток для выполнения сетевых операций с использованием firebase.

Обратные вызовы для слушателей Firebase выполняются только в основном потоке пользовательского интерфейса. Однако, если у вас есть большой объем задач, которые нужно выполнить, вы можете использовать AsyncTask внутри самого обратного вызова.

2
Amit Upadhyay 24 Дек 2016 в 18:20
Метод onDataChange() фактически выполняется в потоке пользовательского интерфейса
 – 
Tord Larsen
24 Дек 2016 в 14:44
Обратные вызовы для ваших слушателей Firebase выполняются в основном потоке пользовательского интерфейса.
 – 
Amit Upadhyay
24 Дек 2016 в 14:47
Хотя, если я запустил слушателей в doInBackground(), обратные вызовы FireBase также будут происходить в фоновом потоке.
 – 
Tord Larsen
24 Дек 2016 в 14:51
Вы можете использовать AsyncTask внутри самого обратного вызова, если вам нужно выполнить большой объем работы
 – 
Amit Upadhyay
24 Дек 2016 в 14:58
1
С Рождеством @ErikHellberg :)
 – 
Amit Upadhyay
24 Дек 2016 в 15:16