Firebaseに保存されたビデオを表示するアプリを作成しています。動画のリストをページ分割して、最新の20本の動画を一度に取得する必要があります。
これが私がうまくいくと思ったコードです
private void getVideos() {
Query videosQuery = FirebaseUtil.getVideosRef();
videosQuery.startAt(0);
videosQuery.endAt(1);
ChildEventListener videosChildEventListener = new ChildEventListener() {
@Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
String date = dataSnapshot.getKey();
String temp = date;
}
@Override
public void onChildChanged(DataSnapshot dataSnapshot, String s) {
}
@Override
public void onChildRemoved(DataSnapshot dataSnapshot) {
}
@Override
public void onChildMoved(DataSnapshot dataSnapshot, String s) {
}
@Override
public void onCancelled(DatabaseError databaseError) {
Log.d(tag, "database error");
}
};
ValueEventListener videoValueEventListener = new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
String date = dataSnapshot.getKey();
String temp = date;
long count = dataSnapshot.getChildrenCount();
String value = dataSnapshot.getValue().toString();
temp = value;
}
@Override
public void onCancelled(DatabaseError databaseError) {
Log.d(tag, "database error");
}
};
// videosQuery.addChildEventListener(videosChildEventListener);
videosQuery.addValueEventListener(videoValueEventListener);
}
ただし、上記のコードは、限られたビデオではなく、ビデオのリスト全体を取得します。ページネーションをどのように実装できますか。
以下は、最新のノードを最初に表示するページネーションに使用しているコードです。
public void getImages() {
Query imagesQuery = FirebaseDatabase.getInstance().getReference().child("englishDps").child(mChildName).orderByKey().limitToLast(21);
ChildEventListener childEventListener = new ChildEventListener() {
@Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
Image image = dataSnapshot.getValue(Image.class);
image.setNodeKey(dataSnapshot.getKey());
mTempImages.add(image);
if (mTempImages.size() == 21) {
mLastKey = mTempImages.get(0).getNodeKey();
Collections.reverse(mTempImages);
mTempImages.remove(mTempImages.size() - 1);
mImages.addAll(mTempImages);
setAdapter();
}
}
@Override
public void onChildChanged(DataSnapshot dataSnapshot, String s) {
}
@Override
public void onChildRemoved(DataSnapshot dataSnapshot) {
}
@Override
public void onChildMoved(DataSnapshot dataSnapshot, String s) {
}
@Override
public void onCancelled(DatabaseError databaseError) {
if (isAdded()) {
Toast.makeText(getActivity(), "Problem loading more images...", Toast.LENGTH_LONG).show();
}
}
};
imagesQuery.addChildEventListener(childEventListener);
}
@Override
public void getMoreImages() {
if (!mGettingMoreImages) {
mGettingMoreImages = true;
Query imagesQuery = FirebaseDatabase.getInstance().getReference("englishDps").child(mChildName).orderByKey().endAt(mLastKey).limitToLast(21);
ChildEventListener childEventListener = new ChildEventListener() {
@Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
Image image = dataSnapshot.getValue(Image.class);
image.setNodeKey(dataSnapshot.getKey());
mMoreImages.add(image);
if (mMoreImages.size() == 21) {
mLastKey = mMoreImages.get(0).getNodeKey();
Collections.reverse(mMoreImages);
mMoreImages.remove(mMoreImages.size() - 1);
mImages.addAll(mMoreImages);
mMoreImages.clear();
mGettingMoreImages = false;
mImagesAdapter.notifyDataSetChanged();
return;
}
if (mLastKey.equalsIgnoreCase(image.getNodeKey())) {
Collections.reverse(mMoreImages);
mImages.addAll(mMoreImages);
mMoreImages.clear();
mGettingMoreImages = false;
mImagesAdapter.onNoMoreImages();
;
mImagesAdapter.notifyDataSetChanged();
}
}
@Override
public void onChildChanged(DataSnapshot dataSnapshot, String s) {
}
@Override
public void onChildRemoved(DataSnapshot dataSnapshot) {
}
@Override
public void onChildMoved(DataSnapshot dataSnapshot, String s) {
}
@Override
public void onCancelled(DatabaseError databaseError) {
if (isAdded()) {
Toast.makeText(getActivity(), "Problem loading more images...", Toast.LENGTH_LONG).show();
}
}
};
imagesQuery.addChildEventListener(childEventListener);
}
}
LimitToFirst/limitToLastメソッドを使用して、限られた数の結果を取得する必要があります。
videosQuery.orderByKey().limitToFirst(20)
https://www.firebase.com/docs/web/api/query/limittofirst.html
ビデオの命名規則を変更して、先頭の0(つまり、video01、video02 ... video10、video11)を含めることを検討する必要があります。上記のコードでは、上記のとおりに表示されます(順序が間違っていると思われますか?)
または、Java経由で動画を追加する場合、Push()経由でfirebaseにuniqueidを作成させることができます。 uniqueidは、時系列に並べ替えられるように生成されます。これは、最新の(追加された?)ビデオを取得する必要があるように思えます。
mPageEndOffset = 0;
mPageLimit = 10;
mPageEndOffset += mPageLimit;
deviceListQuery = mDatabase.child("users")
.orderByChild("id").limitToFirst(mPageLimit).startAt(mPageEndOffset);
deviceListQuery.addValueEventListener(YourActivity.this);
Firebaseリアルタイムデータベースノードを介してページ分割する次の方法があります。
_private void getUsers(String nodeId) {
Query query;
if (nodeId == null)
query = FirebaseDatabase.getInstance().getReference()
.child(Consts.FIREBASE_DATABASE_LOCATION_USERS)
.orderByKey()
.limitToFirst(mPostsPerPage);
else
query = FirebaseDatabase.getInstance().getReference()
.child(Consts.FIREBASE_DATABASE_LOCATION_USERS)
.orderByKey()
.startAt(nodeId)
.limitToFirst(mPostsPerPage);
query.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
UserModel user;
List<UserModel> userModels = new ArrayList<>();
for (DataSnapshot userSnapshot : dataSnapshot.getChildren()) {
userModels.add(userSnapshot.getValue(UserModel.class));
}
mAdapter.addAll(userModels);
mIsLoading = false;
}
@Override
public void onCancelled(DatabaseError databaseError) {
mIsLoading = false;
}
});
}
_
ページ分割されたデータの最後に到達するたびに、getUsers(mAdapter.getLastItemId());
を呼び出してから、次のレコードセットを取得します。
Firestoreでのクエリへのページネーションの実装に関する この質問 は、この質問の複製としてマークされているため、ここで回答します。
Android Firestoreでクエリをページ分割します
_Query query = db.collection("cities")
.orderBy("population")
.limit(25);
Query next = query;
private void loadCities() {
query = next;
query.get()
.addOnSuccessListener(new OnSuccessListener<QuerySnapshot>() {
@Override
public void onSuccess(QuerySnapshot documentSnapshots) {
// Get the last visible document
DocumentSnapshot lastVisible =
documentSnapshots.getDocuments()
.get(documentSnapshots.size() -1);
// Construct a new query starting at this document,
// get the next 25 cities.
next = db.collection("cities")
.orderBy("population")
.startAfter(lastVisible)
.limit(25);
}
});
}
_
さらに多くの都市をロードする必要があるときはいつでもloadCities()
メソッドを呼び出してください。
Androidのページングライブラリを使用して、firebaseデータベースから取得したデータのページネーションを実装できます。データはリサイクラビューに表示され、ページングコンポーネントはユーザースクロールイベントに応じてページを取得します。
ページングデータソースは、表示するページのクエリパラメーターを渡すfirebase DAOオブジェクトを呼び出し、提供されたコールバックを使用して結果をページングコンポーネントに返します。
参照用の完全な例を示します http://www.zoftino.com/firebase-pagination-using-Android-paging-library
これが、firebaseデータベースからのページネーションの実装方法です。 100件のメッセージがある場合を考えてみましょう。だから、最初にfirebaseから最後の20個のメッセージ、つまり81から100をロードします。次に、スクロールアップ時にgetMoreMessages()
functionを呼び出して、61から80などの次の20個のメッセージをロードします。
public class ChatActivity extends Activity {
String chat_id = "";
long mTotalChildren = 0;
boolean loading = false;
ChildEventListener childEventListenerMain, childEventListenerPager;
ChatActivity mContext = ChatActivity.this;
MessageAdapter messageAdapter;
@BindView(R.id.pb_messages)
ProgressBar pb_messages;
@BindView(R.id.ll_audio)
LinearLayout llAudio;
@BindView(R.id.tv_record_time)
AppCompatTextView tvRecordTime;
@BindView(R.id.tv_cancel)
AppCompatTextView tvCancel;
@BindView(R.id.iv_send)
AppCompatImageView ivSend;
@BindView(R.id.iv_record)
AppCompatImageView ivRecord;
@BindView(R.id.ab_layout)
AppBarLayout abLayout;
@BindView(R.id.messages)
RecyclerView rvMessages;
@BindView(R.id.iv_chat_icon)
SimpleDraweeView ivChatIcon;
@BindView(R.id.iv_camera)
AppCompatImageView ivCamera;
@BindView(R.id.iv_gallery)
AppCompatImageView ivGallery;
@BindView(R.id.message_input)
AppCompatEditText messageInput;
@BindView(R.id.tv_send)
AppCompatTextView tvSend;
@BindView(R.id.toolbar_title)
AppCompatTextView toolbarTitle;
@BindView(R.id.toolbar_status)
AppCompatTextView toolbarStatus;
@BindView(R.id.ll_send)
LinearLayout llSend;
int categoryId, senderId, receiverId, offerId;
String mLastKey;
LinearLayoutManager layoutManager;
private ArrayList<MessageModel> messageArrayList = new ArrayList<>();
private ArrayList<MessageModel> tempMessageArrayList = new ArrayList<>();
@Override
public int getLayoutId() {
return R.layout.activity_chat;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
messageAdapter = new MessageAdapter(mContext, messageArrayList) {
};
layoutManager = new LinearLayoutManager(mContext);
rvMessages.setLayoutManager(layoutManager);
rvMessages.setItemAnimator(new DefaultItemAnimator());
rvMessages.setAdapter(messageAdapter);
rvMessages.setHasFixedSize(true);
rvMessages.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
}
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
if (messageArrayList.size() >= 20 &&
!loading && layoutManager.findFirstVisibleItemPosition() == 0 && messageArrayList.size() < mTotalChildren) {
loading = true;
getMoreMessages();
}
}
});
messageAdapter.notifyDataSetChanged();
//used to scroll up recyclerview when keyboard pops up
rvMessages.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
@Override
public void onLayoutChange(View view, int left, int top, int right, int bottom,
int oldLeft, int oldTop, int oldRight, int oldBottom) {
if (bottom < oldBottom) {
rvMessages.postDelayed(new Runnable() {
@Override
public void run() {
rvMessages.scrollToPosition(messageArrayList.size() - 1);
}
}, 100);
}
}
});
loading = true;
getMessages();
}
public void getMessages() {
FirebaseDatabase.getInstance().getReference().child(pathtomsgs).addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
Log.e("childrenCount", String.valueOf(+dataSnapshot.getChildrenCount()));
mTotalChildren = dataSnapshot.getChildrenCount();
}
@Override
public void onCancelled(DatabaseError databaseError) {
}
});
Query messageQuery = FirebaseDatabase.getInstance().getReference().child(pathtomsgs).limitToLast(20);
childEventListenerMain = new ChildEventListener() {
@Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
loading = true;
MessageModel messageModel = dataSnapshot.getValue(MessageModel.class);
if (messageModel != null) {
messageModel.chat_id = chat_id;
messageModel.message_id = dataSnapshot.getKey();
messageArrayList.add(messageModel);
messageAdapter.notifyDataSetChanged();
mLastKey = messageArrayList.get(0).message_id;
rvMessages.scrollToPosition(messageArrayList.size() - 1);
}
}
@Override
public void onChildChanged(DataSnapshot dataSnapshot, String s) {
}
@Override
public void onChildRemoved(DataSnapshot dataSnapshot) {
}
@Override
public void onChildMoved(DataSnapshot dataSnapshot, String s) {
}
@Override
public void onCancelled(DatabaseError databaseError) {
Toast.makeText(mContext, "Problem loading more images...", Toast.LENGTH_LONG).show();
}
};
messageQuery.addChildEventListener(childEventListenerMain);
ValueEventListener messageChildSINGLEValueEventListener = new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
pb_messages.setVisibility(View.GONE);
System.out.println("We're done loading messages " + dataSnapshot.getChildrenCount() + " items");
loading = false;
}
@Override
public void onCancelled(DatabaseError databaseError) {
}
};
messageQuery.addListenerForSingleValueEvent(messageChildSINGLEValueEventListener);
}
public void getMoreMessages() {
tempMessageArrayList.clear();
Query messageQuery = FirebaseDatabase.getInstance().getReference().child(pathtomsgs).orderByKey().endAt(mLastKey).limitToLast(20);
childEventListenerPager = new ChildEventListener() {
@Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
loading = true;
MessageModel messageModel = dataSnapshot.getValue(MessageModel.class);
if (messageModel != null) {
messageModel.chat_id = chat_id;
messageModel.message_id = dataSnapshot.getKey();
tempMessageArrayList.add(messageModel);
}
}
@Override
public void onChildChanged(DataSnapshot dataSnapshot, String s) {
}
@Override
public void onChildRemoved(DataSnapshot dataSnapshot) {
}
@Override
public void onChildMoved(DataSnapshot dataSnapshot, String s) {
}
@Override
public void onCancelled(DatabaseError databaseError) {
Toast.makeText(mContext, "Problem loading more images...", Toast.LENGTH_LONG).show();
}
};
messageQuery.addChildEventListener(childEventListenerPager);
ValueEventListener messageChildSINGLEValueEventListener = new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
System.out.println("We're done loading messages " + dataSnapshot.getChildrenCount() + " items");
tempMessageArrayList.remove(tempMessageArrayList.size() - 1);
messageArrayList.addAll(0, tempMessageArrayList);
mLastKey = messageArrayList.get(0).message_id;
messageAdapter.notifyDataSetChanged();
//rvMessages.scrollToPosition(20);
layoutManager.scrollToPositionWithOffset(19, 0);
loading = false;
}
@Override
public void onCancelled(DatabaseError databaseError) {
}
};
messageQuery.addListenerForSingleValueEvent(messageChildSINGLEValueEventListener);
}
@Override
protected void onDestroy() {
FirebaseDatabase.getInstance().getReference().child(pathtomsgs).removeEventListener(childEventListenerPager);
FirebaseDatabase.getInstance().getReference().child(pathtomsgs).removeEventListener(childEventListenerMain);
super.onDestroy();
}
}
Firebaseデータベースページングライブラリを次のコードとして使用することで実現できます。このコードでは、Post
をデータモデル項目として、PostViewHolder
をViewHolderとして示しました。
//Initialize RecyclerView
mRecyclerView = findViewById(R.id.recycler_view);
mRecyclerView.setHasFixedSize(true);
LinearLayoutManager mManager = new LinearLayoutManager(this);
mRecyclerView.setLayoutManager(mManager);
//Initialize Database
mDatabase = FirebaseDatabase.getInstance().getReference().child("posts");
//Initialize PagedList Configuration
PagedList.Config config = new PagedList.Config.Builder()
.setEnablePlaceholders(false)
.setPrefetchDistance(5)
.setPageSize(10)
.build();
//Initialize FirebasePagingOptions
DatabasePagingOptions<Post> options = new DatabasePagingOptions.Builder<Post>()
.setLifecycleOwner(this)
.setQuery(mDatabase, config, Post.class)
.build();
//Initialize Adapter
mAdapter = new FirebaseRecyclerPagingAdapter<Post, PostViewHolder>(options) {
@NonNull
@Override
public PostViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
return new PostViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_list, parent, false));
}
@Override
protected void onBindViewHolder(@NonNull PostViewHolder holder,
int position,
@NonNull Post model) {
holder.setItem(model);
}
@Override
protected void onLoadingStateChanged(@NonNull LoadingState state) {
switch (state) {
case LOADING_INITIAL:
case LOADING_MORE:
// Do your loading animation
mSwipeRefreshLayout.setRefreshing(true);
break;
case LOADED:
// Stop Animation
mSwipeRefreshLayout.setRefreshing(false);
break;
case FINISHED:
//Reached end of Data set
mSwipeRefreshLayout.setRefreshing(false);
break;
case ERROR:
retry();
break;
}
}
@Override
protected void onError(@NonNull DatabaseError databaseError) {
super.onError(databaseError);
mSwipeRefreshLayout.setRefreshing(false);
databaseError.toException().printStackTrace();
}
};
//Set Adapter to RecyclerView
mRecyclerView.setAdapter(mAdapter);
参照用に以下のURLをご覧ください https://firebaseopensource.com/projects/patilshreyas/firebaserecyclerpagination/app/readme.md/ ここには、firebaseデータのページネーションの実装に役立つライブラリの実装がありますRecyclerView
これがお役に立てば幸いです!
最大値未満の場合、承認されたanswearは機能しません。データベース内のitmes(21)。これは受け入れられた答えに基づいた私のソリューションです:
0)変数を設定
private String lastMessageKey;
private int totalItemCount;
private int lastVisibleItem;
private boolean isLoadingMoreFollowers = false;
private boolean hasMoreItems = true;
private boolean hasShownNoMoreItemsToast = false;
private boolean initialLoad = true;
private final int MAX_LOAD_ITEMS = 11;
private final int VISIBLE_TRESHOLD = 1;
1)リスナーを設定します。
private void setMessageListener() {
if (childEventListener == null) {
mmessageArrayList.clear();
final ArrayList<Mmessage> tempMmessages = new ArrayList<>();
query = mDatabaseInstace.getReference().child(chat1).child(F.CHATS).child(F.MESSAGES).orderByKey().limitToLast(MAX_LOAD_ITEMS-1);
childEventListener = new ChildEventListener() {
@Override
public void onChildAdded(@NonNull DataSnapshot dataSnapshot, @Nullable String s) {
Log.d(TAG, "onChildAdded: -----------------> " + dataSnapshot);
Log.d(TAG, "onChildAdded: -----------------> " + s);
tempMmessages.add(dataSnapshot.getValue(Mmessage.class));
preloadMessagePics(tempMmessages);
if (initialLoad) {
lastMessageKey = tempMmessages.get(0).getMessagePushKey();
initialLoad = false;
}
mmessageArrayList.add(tempMmessages.size()-1, tempMmessages.get(0));
messageAdapter.notifyDataSetChanged();
tempMmessages.clear();
}
@Override
public void onChildChanged(@NonNull DataSnapshot dataSnapshot, @Nullable String s) {
Log.d(TAG, "onChildChanged: --------------------------------->");
}
@Override
public void onChildRemoved(@NonNull DataSnapshot dataSnapshot) {
Log.d(TAG, "onChildRemoved: ---------------------------------->");
}
@Override
public void onChildMoved(@NonNull DataSnapshot dataSnapshot, @Nullable String s) {
Log.d(TAG, "onChildMoved: ------------------------------------>");
}
@Override
public void onCancelled(@NonNull DatabaseError databaseError) {
Log.d(TAG, "onCancelled: ------------------------------------->");
}
};
query.addChildEventListener(childEventListener);
}
}
2)さらにリスナーをロードするように設定します。
private void setLoadMoreListener(){
setup.RV_messages.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
totalItemCount = linearLayoutManager.getItemCount();
lastVisibleItem = linearLayoutManager.findLastVisibleItemPosition();
if (!isLoadingMoreFollowers && totalItemCount <= (lastVisibleItem+VISIBLE_TRESHOLD) && (totalItemCount >= MAX_LOAD_ITEMS-1)){
if (hasMoreItems) {
getMoreMessages();
Toast.makeText(homeActivity, "load more items", Toast.LENGTH_SHORT).show();
}else {
if (!hasShownNoMoreItemsToast) {
Toast.makeText(homeActivity, "has no more items", Toast.LENGTH_SHORT).show();
hasShownNoMoreItemsToast = true;
}
}
}
}
});
}
3)より多くのアイテムを取得する:
private void getMoreMessages(){
final ArrayList<Mmessage> tempMmessages = new ArrayList<>();
isLoadingMoreFollowers = true;
loadMoreQuery = mDatabaseInstace.getReference().child(chat1).child(F.CHATS).child(F.MESSAGES).orderByKey().endAt(lastMessageKey).limitToLast(MAX_LOAD_ITEMS);
loadMoreChildEventListener = new ChildEventListener() {
@Override
public void onChildAdded(@NonNull DataSnapshot dataSnapshot, @Nullable String s) {
tempMmessages.add(dataSnapshot.getValue(Mmessage.class));
preloadMessagePics(tempMmessages);
if (tempMmessages.size() == MAX_LOAD_ITEMS){
lastMessageKey = tempMmessages.get(0).getMessagePushKey();
Collections.reverse(tempMmessages);
tempMmessages.remove(0);
mmessageArrayList.addAll(tempMmessages);
isLoadingMoreFollowers = false;
messageAdapter.notifyDataSetChanged();
tempMmessages.clear();
return;
}
if (lastMessageKey.equalsIgnoreCase(tempMmessages.get(tempMmessages.size()-1).getMessagePushKey())){
Collections.reverse(tempMmessages);
tempMmessages.remove(0);
mmessageArrayList.addAll(tempMmessages);
isLoadingMoreFollowers = false;
hasMoreItems = false;
messageAdapter.notifyDataSetChanged();
tempMmessages.clear();
}
}
@Override
public void onChildChanged(@NonNull DataSnapshot dataSnapshot, @Nullable String s) {
}
@Override
public void onChildRemoved(@NonNull DataSnapshot dataSnapshot) {
}
@Override
public void onChildMoved(@NonNull DataSnapshot dataSnapshot, @Nullable String s) {
}
@Override
public void onCancelled(@NonNull DatabaseError databaseError) {
}
};
loadMoreQuery.addChildEventListener(loadMoreChildEventListener);
}
楽しんで!!