所以我将ChildEventListener
和ValueEventListener
添加到了AsyncTask
。
图这种方式主要的ui线程不会被打扰。下面的代码很有用,但问题是当我在exitFirebase()
方法下面终止监听器时会发生什么?
当AsyncTask
启动它时,doInBackground()
添加FireBase监听器,然后通过onPostExecute()
看似退出,但听众正在使AsyncTask
保持正常... < / p>
当我终止听众时会发生什么?
/**
* 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;
}
答案 0 :(得分:2)
所以我将ChildEventListener和ValueEventListener添加到了一个 的AsyncTask。
无需使用AsyncTask
来实施Firebase操作。 Firebase已经过优化。因此,您不需要使用后台线程来使用firebase执行与网络相关的操作。
Firebase侦听器的回调仅在主UI线程上执行。但是,如果要执行大量任务,则可以在回调本身内使用AsyncTask。