2016-06-08 12 views
8

Sto costruendo un'app che mostrerà i video memorizzati su Firebase. L'elenco dei video deve essere impaginato recuperando gli ultimi 20 video alla volta.Impaginazione Android Firebase

enter image description here

Ecco il codice che ho pensato che avrebbe funzionato

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); 

    } 

Ma soprattutto codice recupera intero elenco di video, invece di video limitate. Come si può implementare l'impaginazione.

+0

Hai trovato un via per impaginare? – Raghunandan

+1

Hai ricevuto qualcosa per l'impaginazione? Devo anche implementare l'impaginazione nella mia applicazione usando firebase. –

risposta

6

Di seguito è il codice che sto utilizzando per l'impaginazione che mostra le ultime primo nodo.

 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); 
     } 
    } 
+0

Per favore, dimmi che getMoreImages() è il tuo metodo override ??? Voglio anche usare il concetto di impaginazione come hai usato..Qual è la tua funzionalità onLoadMore ?? –

+0

framment implementa l'interfaccia nel mio codice. Puoi rimuovere la notazione @override –

+0

Potresti spiegare cosa significa '. OnNoMoreImages();' is? Grazie –

3

Si desidera utilizzare i metodi limitToFirst/limitToLast per recuperare un numero limitato di risultati.

videosQuery.orderByKey().limitToFirst(20) 

https://www.firebase.com/docs/web/api/query/limittofirst.html

Si dovrebbe davvero pensare di cambiare la convenzione di denominazione dei tuoi video per includere 0 non significativi (cioè video01, video02 ... video10, video11) perché il codice sopra di loro mostrerà esattamente come si deve loro sopra (che presumo sia fuori servizio?)

In alternativa, se stai aggiungendo i video tramite Java, puoi semplicemente consentire a firebase di creare gli unici tramite push(). Gli uniqueid sono generati in modo da essere ordinati in ordine cronologico, il che suona come se fosse adatto alle tue necessità di catturare i video più recenti (ly added?).

https://www.firebase.com/docs/web/api/firebase/push.html

+0

Provato usando videoQuery.orderByKey(). LimitToLast (2); con ChildEventListener e ancora non è in grado di ottenere una risposta impaginata. –

+1

questa non è veramente una risposta all'impaginazione. Limita solo la risposta unica agli ultimi x film. – alltooconfusingthereforesleep

4
mPageEndOffset = 0; 
mPageLimit = 10; 


mPageEndOffset += mPageLimit; 

deviceListQuery = mDatabase.child("users") 
.orderByChild("id").limitToFirst(mPageLimit).startAt(mPageEndOffset); 

deviceListQuery.addValueEventListener(YourActivity.this); 
+1

Ho un problema per farlo funzionare al contrario, qualche idea? http://stackoverflow.com/questions/40231335/how-to-paginate-firebase-from-the-last-items-to-the-first – Lion789

+0

Aggiungi un campo con un valore decrescente ai dati, ad esempio: unix_timestamp (o timestamp invertito) e utilizzare limitToLast() con la query selezionata. Non abbiamo davvero bisogno dell'impaginazione perché la query di Firebase viene eseguita e restituita velocemente.Io uso una query per ottenere 1000 record in una singola query con non molto ritardo finora sperimentato –

+0

Come si collegherebbe un unix_timestamp (o timestamp invertito)? Attualmente sto aggiungendo un timestamp con il seguente metodo 'ServerValue.TIMESTAMP' – Zen

0

Ho seguente metodo per impaginare attraverso un Firebase nodo del database in tempo reale:

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; 
      } 
     }); 
    } 

Ogni volta raggiungo il fondo dei dati impaginati, che io chiamo il getUsers(mAdapter.getLastItemId()); e poi si porta la prossima serie di record.

ho scritto una guida completa con l'open source campione app su questo che si può verificare in https://blog.shajeelafzal.com/2017/12/13/firebase-realtime-database-pagination-guide-using-recyclerview/

0

Ecco come ho implementato la paginazione dal database Firebase. Considera un caso se abbiamo 100 messaggi. Quindi prima di tutto caricherò gli ultimi 20 messaggi dalla base dei fulmini, cioè da 81 a 100. Quindi, su per scorrere, chiamo la funzione getMoreMessages() per caricare i prossimi 20 messaggi che vanno da 61 a 80 e così via.

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(); 
     } 
    }