Вы можете создать транзакцию и прервать ее, тогда onComplete будет вызываться, когда он находится в сети (данные nline) или в автономном режиме (кешированные данные)
Я ранее создал функцию, которая работала, только если база данных получила соединение, достаточное для выполнения синхронизация. Я исправил проблему, добавив тайм-аут. Я буду работать над этим и проверить, работает ли это. Возможно, в будущем, когда я получу свободное время, я создам андроидскую библиотеку и опубликую ее, но к тому времени это код в kotlin:
/**
* @param databaseReference reference to parent database node
* @param callback callback with mutable list which returns list of objects and boolean if data is from cache
* @param timeOutInMillis if not set it will wait all the time to get data online. If set - when timeout occurs it will send data from cache if exists
*/
fun readChildrenOnlineElseLocal(databaseReference: DatabaseReference, callback: ((mutableList: MutableList<@kotlin.UnsafeVariance T>, isDataFromCache: Boolean) -> Unit), timeOutInMillis: Long? = null) {
var countDownTimer: CountDownTimer? = null
val transactionHandlerAbort = object : Transaction.Handler { //for cache load
override fun onComplete(p0: DatabaseError?, p1: Boolean, data: DataSnapshot?) {
val listOfObjects = ArrayList<T>()
data?.let {
data.children.forEach {
val child = it.getValue(aClass)
child?.let {
listOfObjects.add(child)
}
}
}
callback.invoke(listOfObjects, true)
}
override fun doTransaction(p0: MutableData?): Transaction.Result {
return Transaction.abort()
}
}
val transactionHandlerSuccess = object : Transaction.Handler { //for online load
override fun onComplete(p0: DatabaseError?, p1: Boolean, data: DataSnapshot?) {
countDownTimer?.cancel()
val listOfObjects = ArrayList<T>()
data?.let {
data.children.forEach {
val child = it.getValue(aClass)
child?.let {
listOfObjects.add(child)
}
}
}
callback.invoke(listOfObjects, false)
}
override fun doTransaction(p0: MutableData?): Transaction.Result {
return Transaction.success(p0)
}
}
В коде, если установлен тайм-аут, тогда I настройте таймер, который вызовет транзакцию с прерыванием. Эта транзакция будет вызываться даже в автономном режиме и будет предоставлять онлайн-или кешированные данные (в этой функции действительно существует вероятность того, что эти данные будут кэшированы). Затем я делаю транзакцию с успехом. OnComplete
будет вызван ТОЛЬКО, если мы получим ответ от базы данных firebase. Теперь мы можем отменить таймер (если не null) и отправить данные для обратного вызова.
Эта реализация делает dev на 99% уверенным, что данные находятся в кеше или находятся в режиме онлайн.
Если вы хотите ускорить работу в автономном режиме (чтобы не допустить тупо с тайм-аутом, когда, очевидно, база данных не подключена), проверьте, подключена ли база данных до использования функции выше:
DatabaseReference connectedRef = FirebaseDatabase.getInstance().getReference(".info/connected");
connectedRef.addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot snapshot) {
boolean connected = snapshot.getValue(Boolean.class);
if (connected) {
System.out.println("connected");
} else {
System.out.println("not connected");
}
}
@Override
public void onCancelled(DatabaseError error) {
System.err.println("Listener was cancelled");
}
});
Если вы просто хотите напечатать метку для каждого объекта, вы можете использовать цикл или понимание списка:
print [vertex.label for vertex in x]
Но чтобы ответить на ваш исходный вопрос, вам нужно определить __repr__
чтобы получить право вывода списка. Это может быть так просто:
def __repr__(self):
return str(self)
Если вы хотите получить немного больше информации, кроме ответа Даниэля Розмана:
__repr__
и __str__
- две разные вещи в python. (обратите внимание, однако, что если вы определили только __repr__
, вызов class.__str__
переводится в вызов class.__repr__
)
Цель __repr__
должна быть однозначной. Кроме того, когда возможно сервер, вы должны определить реестр так, чтобы (в вашем случае) eval(repr(instance)) == instance
С другой стороны, цель __str__
должна быть переименована; так что имеет значение, если вам нужно распечатать экземпляр на экране (для пользователя, возможно), если вам не нужно это делать, тогда не реализуйте его (и, опять же, если str в не реализован будет называться repr)
Кроме того, при типе вещей в интерпретаторе Idle он автоматически вызывает повторное представление вашего объекта. Или когда вы печатаете список, он вызывает list.__str__
(который идентичен list.__repr__
), который вызывает в свою очередь репрезентативное представление любого элемента, содержащего список. Это объясняет поведение, которое вы получаете, и, надеюсь, как его исправить