Как будто вы пытаетесь получить доступ к объекту, который является null
. Рассмотрим ниже пример:
TypeA objA;
. В это время вы только что объявили этот объект, но не инициализировали или не инициализировали. И всякий раз, когда вы пытаетесь получить доступ к каким-либо свойствам или методам в нем, он будет генерировать NullPointerException
, что имеет смысл.
См. Также этот пример:
String a = null;
System.out.println(a.toString()); // NullPointerException will be thrown
Firebase: как отобразить поток элементов в обратном порядке с лимитом для каждого запроса и индикатором кнопки «загрузить больше».
FBRef.child ("childName") .limitToLast (loadMoreLimit) // loadMoreLimit = 10, например
this.FBRef .child ("childName") .endAt (null, lastThreadId) // Получить это с предыдущего шага .limitToLast (loadMoreLimit + 2)
list = snapObjectAsArray; // The list is an array from snapObject
lastItemId = key; // get the first key of the list
if (list.length < loadMoreLimit+1) {
lastItemId = false;
}
if (list.length > loadMoreLimit+1) {
list.pop();
}
if (list.length > loadMoreLimit) {
list.shift();
}
// Return the list.reverse() and lastItemId
// If lastItemId is an ID, it will be used for the next reference and a flag to show the "load more" button.
}
Я сделал это с помощью preend.
query.orderByChild('sell').limitToLast(4).on("value", function(snapshot){
snapshot.forEach(function (childSnapshot) {
// PREPEND
});
});
Кто-то указал, что есть два способа сделать это:
Самый простой способ, который я нашел для этого, - использовать параметр 1, но через LinkedList
. Я просто добавляю каждый из объектов к передней части стека. Он достаточно гибкий, чтобы позволить использовать список в файлах ListView
или RecyclerView
. Таким образом, несмотря на то, что они приходят по порядку от старости к новейшим, вы все равно можете просматривать или загружать самые новые до самых старых.
У меня тоже была эта проблема, я нашел очень простое решение, которое в любом случае не включало манипулирование данными. Если вы разорёте результат в DOM, в каком-то списке. Вы можете использовать flexbox и настроить класс для изменения элементов в своем контейнере.
.reverse {
display: flex;
flex-direction: column-reverse;
}
Есть лучший способ. Вы должны заказать минус-метку сервера. Как получить отрицательную отметку времени сервера даже в автономном режиме? Это помогает скрытое поле. Связанный фрагмент документа:
var offsetRef = new Firebase("https://<YOUR-FIREBASE-APP>.firebaseio.com/.info/serverTimeOffset");
offsetRef.on("value", function(snap) {
var offset = snap.val();
var estimatedServerTimeMs = new Date().getTime() + offset;
});
В Android существует способ фактического изменения данных в Arraylist объектов через адаптер. В моем случае я не мог использовать LayoutManager для изменения результатов в порядке убывания, так как я использовал горизонтальный Recyclerview для отображения данных. Установка следующих параметров в recyclerview испортила мой опыт работы с интерфейсом:
llManager.setReverseLayout(true);
llManager.setStackFromEnd(true);
Единственный рабочий путь, который я нашел вокруг этого, был через метод BindViewHolder адаптера RecyclerView:
@Override
public void onBindViewHolder(final RecyclerView.ViewHolder holder, int position) {
final SuperPost superPost = superList.get(getItemCount() - position - 1);
}
Надеюсь, этот ответ поможет всем разработчикам, которые борются с этой проблемой в Firebase.
Поскольку этот ответ был написан, Firebase добавила функцию, которая позволяет упорядочивать любой дочерний элемент или значение. Таким образом, теперь есть четыре способа заказа данных: по ключу, по значению, по приоритету или по значению любого именованного дочернего элемента. [Gg]
Основные подходы остаются неизменными, хотя:
] 1. Добавьте дочернее свойство с инвертированной меткой времени, а затем закажите это.
2. Прочитайте их в порядке возрастания, а затем инвертируйте их на клиенте.
Firebase поддерживает извлечение дочерних узлов коллекции двумя способами:
- по имени
- по приоритету
То, что вы получаете сейчас, называется по имени, что бывает хронологическим. Это не совпадение кстати: когда вы
push
элемент в коллекцию, имя создается, чтобы гарантировать, что дети упорядочены таким образом. Чтобы процитировать документацию Firebase дляpush
:Уникальное имя, сгенерированное push (), имеет префикс с меткой времени, созданной клиентом, так что результирующий список будет хронологически отсортированы.
В руководстве Firebase по упорядоченным данным есть это сказать по теме:
Как данные упорядочены
По умолчанию дети в узле Firebase сортируются лексикографически по имени. Использование
push()
может генерировать дочерние имена, которые, естественно, сортируются в хронологическом порядке, но многие приложения требуют, чтобы их данные сортировались другими способами. Firebase позволяет разработчикам указывать порядок элементов в списке, указав собственный приоритет для каждого элемента.Самый простой способ получить нужное поведение - также указать всегда убывающий приоритет, когда вы добавите элемент:
var ref = new Firebase('https://your.firebaseio.com/sell'); var item = ref.push(); item.setWithPriority(yourObject, 0 - Date.now());
Обновить
Вам также придется искать детей по-другому:
fbl.child('sell').startAt().limit(20).on('child_added', function(fbdata) { console.log(fbdata.exportVal()); })
В моем тесте с использованием
on('child_added'
гарантирует, что последние несколько детей добавлены в обратном хронологическом порядке. С другой стороны, с помощьюon('value'
возвращает их в порядке их имени.Обязательно прочитайте раздел «Чтение упорядоченных данных» , в котором объясняется использование
child_*
события для извлечения (упорядоченных) детей.Бит для демонстрации этого: http://jsbin.com/nonawe/3/watch?js,console
На самом деле нет способа, но, похоже, у нас есть recyclerview, у нас может быть это
query=mCommentsReference.orderByChild("date_added");
query.keepSynced(true);
// Initialize Views
mRecyclerView = (RecyclerView) view.findViewById(R.id.recyclerView);
mManager = new LinearLayoutManager(getContext());
// mManager.setReverseLayout(false);
mManager.setReverseLayout(true);
mManager.setStackFromEnd(true);
mRecyclerView.setHasFixedSize(true);
mRecyclerView.setLayoutManager(mManager);
Чтобы увеличить ответ Фрэнка, можно также захватить самые последние записи - даже если вы не потрудились упорядочить их с использованием приоритетов - просто используя endAt().limit(x)
, как это demo :
var fb = new Firebase(URL);
// listen for all changes and update
fb.endAt().limit(100).on('value', update);
// print the output of our array
function update(snap) {
var list = [];
snap.forEach(function(ss) {
var data = ss.val();
data['.priority'] = ss.getPriority();
data['.name'] = ss.name();
list.unshift(data);
});
// print/process the results...
}
Обратите внимание, что это довольно показательно даже до тысячи записей (при условии, что полезная нагрузка мала).
Эта грубая сила также может быть оптимизирована для работы с большими данными или большими записями, выполняя такие функции, как мониторинг child_added
/ child_removed
/ child_moved
вместо value
и используя debounce для применения обновлений DOM навалом, а не отдельно.
Обновления DOM, естественно, являются стервой независимо от подхода , как только вы попадаете в сотни элементов, так что подход debounce (или решение React.js, который по сути является debub uber) - отличный инструмент для работы.
Чтобы добавить к ответу Дэйва Вавры, я использую отрицательную метку времени, так как мой sort_key
нравится так
Установка
const timestamp = new Date().getTime();
const data = {
name: 'John Doe',
city: 'New York',
sort_key: timestamp * -1 // Gets the negative value of the timestamp
}
Получение
const ref = firebase.database().ref('business-images').child(id);
const query = ref.orderByChild('sort_key');
return $firebaseArray(query); // AngularFire function
Это позволяет извлекать все объекты от самых новых до самых старых. Вы также можете $indexOn
sortKey
сделать его еще быстрее
timestamp * 1
? Является ли этот javascript конкретным?
– Jemshit Iskenderov
7 February 2018 в 14:21
timestamp * -1
. Это приведет к отрицательному значению
– Kurai Bankusu
7 February 2018 в 15:27
Поскольку firebase 2.0.x вы можете использовать limitLast()
для достижения этого:
fbl.child('sell').orderByValue().limitLast(20).on("value", function(fbdataSnapshot) {
// fbdataSnapshot is returned in the ascending order
// you will still need to order these 20 items in
// in a descending order
}
Вот ссылка на объявление: Дополнительные возможности запросов в Firebase
append
вы можете использовать prepend
для добавления элементов в обратном порядке.
– Mygod
14 July 2015 в 01:52
Вы ищете limitTolast (Int x). Это даст вам последние «x» более высокие элементы вашей базы данных (они находятся в порядке возрастания), но они являются «x» более высокими элементами
, если вы получили в своей базе данных {10,300,150,240,2,24,220}
этот метод:
myFirebaseRef.orderByChild("highScore").limitToLast(4)
выведет вас: {150,220,240,300}
Вы можете добавить столбец с именем orderColumn, где вы сэкономите время, когда
Long refrenceTime = "large future time";
Long currentTime = "currentTime";
Long order = refrenceTime - currentTime;
теперь сохраняете длинный порядок в столбце с именем orderColumn и когда вы извлекаете данные в качестве orderBy (orderColumn) вы получите то, что вам нужно.
просто используйте reverse()
в массиве, предположим, что если вы сохраняете значения в массиве items[]
, тогда выполните this.items.reverse()
ref.subscribe(snapshots => {
this.loading.dismiss();
this.items = [];
snapshots.forEach(snapshot => {
this.items.push(snapshot);
});
**this.items.reverse();**
},
Я использую ReactFire для легкой интеграции Firebase.
В основном, это помогает мне хранить данные в состоянии компонента, как array
. Тогда все, что мне нужно использовать, это функция reverse()
( подробнее )
Вот как я это достигаю:
import React, { Component, PropTypes } from 'react';
import ReactMixin from 'react-mixin';
import ReactFireMixin from 'reactfire';
import Firebase from '../../../utils/firebaseUtils'; // Firebase.initializeApp(config);
@ReactMixin.decorate(ReactFireMixin)
export default class Add extends Component {
constructor(args) {
super(args);
this.state = {
articles: []
};
}
componentWillMount() {
let ref = Firebase.database().ref('articles').orderByChild('insertDate').limitToLast(10);
this.bindAsArray(ref, 'articles'); // bind retrieved data to this.state.articles
}
render() {
return (
<div>
{
this.state.articles.reverse().map(function(article) {
return <div>{article.title}</div>
})
}
</div>
);
}
}
У меня есть переменная date (long) и вы хотите сохранить новейшие элементы в верхней части списка. Итак, я сделал это: