Поэтому я добавил 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 ответ
Поэтому я добавил ChildEventListener и ValueEventListener в AsyncTask.
Нет необходимости использовать AsyncTask
для реализации операций Firebase. Firebase уже оптимизирована. Таким образом, вам не нужно использовать фоновый поток для выполнения сетевых операций с использованием firebase.
Обратные вызовы для слушателей Firebase выполняются только в основном потоке пользовательского интерфейса. Однако, если у вас есть большой объем задач, которые нужно выполнить, вы можете использовать AsyncTask внутри самого обратного вызова.
Похожие вопросы
Новые вопросы
android
Android — это мобильная операционная система Google, используемая для программирования или разработки цифровых устройств (смартфонов, планшетов, автомобилей, телевизоров, одежды, очков, IoT). Для тем, связанных с Android, используйте теги, специфичные для Android, такие как android-intent, android-activity, android-adapter и т. д. Для вопросов, отличных от разработки или программирования, но связанных с Android framework, используйте эту ссылку: https://android .stackexchange.com.
onDataChange()
фактически выполняется в потоке пользовательского интерфейсаdoInBackground()
, обратные вызовы FireBase также будут происходить в фоновом потоке.