В настоящее время я использую следующий подход:
Предположим, моя база данных firebase состоит из списка объектов, которые можно десериализовать в следующем формате:
class MyClass{
public String myClassUniqueID;
... other attributes;
}
Для db i будет обрабатывать весь жизненный цикл слушателя события-значения в моей собственной деятельности (то есть присоединяться к ссылке на db через dbRef.addValueEventListener(dbListener);
или dbRef.removeEventListener(dbListener);
, но процесс создания этого dbListener
и передачи ему необходимых задач будет управляться с помощью следующей служебной функции:
public interface DbListenerActions {
void onMyClassObjFound(@NonNull MyClass matchedObj);
default void onMyClassObjNOTFound() {
}
}
public static ValueEventListener getMyClassObjectFinderListener(String id, DbListenerActions actions) {
Log.e(TAG, "onDataChange: our id:" + id);
ValueEventListener dbListener = new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot dbSnapshot) {
for (DataSnapshot currChildSnap : dbSnapshot.getChildren()) {
String currChildKey = currChildSnap.getKey();
MyClass currChildValue = currChildSnap.getValue(MyClass.class);
if (currChildKey == null) {
Log.e(TAG, "onDataChange: currChildKey is null. continuing");
continue;
}
if (currChildValue == null) {
Log.e(TAG, "onDataChange: currChildValue is null.continuing");
continue;
}
if (currChildValue.myClassUniqueID.equals(id)) {
Log.e(TAG, "onDataChange: currChildValue id matches our id ");
Log.e(TAG, "onDataChange: performing action and RETURNING(i.e getting out of this callback)");
//do stuff here
actions.onMyClassObjFound(currChildValue);
return;
} else {
Log.e(TAG, "onDataChange: current obj DOES NOT matches our id. continuing");
Log.e(TAG, "onDataChange: current object ID :" + currChildValue.myClassUniqueID);
Log.e(TAG, "onDataChange: --------------------------------------------------------------");
continue;
}
}
Log.e(TAG, "onDataChange: user not found, performing not found action" );
actions.onMyClassObjNOTFound();
}
@Override
public void onCancelled(@NonNull DatabaseError databaseError) {
}
};
return dbListener;
}
Таким образом, я могу получить необходимую информацию журнала, которую я хочу во время отладки, и так как есть только 2 возможных действия, которые я хочу выполнить, я получаю гораздо больше уверенности в работе моего слушателя: 50 строк необходимого, но избыточного кода из 11 операций, объединенных в одну служебную функцию!
Теперь все, что мне нужно написать, - это небольшая, более простая для отладки кусок кода в каждом из моих действий:
ValueEventListener dbListener=getMyClassObjectFinderListener("some_id", new DbListenerActions() {
@Override
public void onMyClassObjFound(@NonNull MyClass matchedObj) {
//callSomeFunction()
// callSomeOtherFunction(matchedObj)
//...
}
});
Так как я сделал onMyClassObjNOTFound(..)
функцию default
, мне даже не нужно пров Я думаю, что если я действительно не хочу выполнять какие-то действия там. Так что все это хорошо работает для меня: D
Я тоже спросил в твиттере об этом, кто-то сказал мне, что абстрактный класс также может быть использован для такой вещи. Мне не пришлось больше там исследовать, но если кто-то тоже знает об этом подходе, то дайте мне знать!