I'm using a FirebaseIndexRecyclerAdapter as described on https://github.com/firebase/FirebaseUI-Android/tree/master/database. But my list has many items and I want to only load a few items at first and then lazy load the rest when the user scrolls up.
My first thought was that I could use mKeyRef.limitToLast(5) but then updating this requires recreating the Adapter, right?
How do I achieve this lazy-loading mechanic?
RecyclerView recycler = (RecyclerView) findViewById(R.id.messages_recycler);
recycler.setHasFixedSize(true);
recycler.setLayoutManager(new LinearLayoutManager(this));
mAdapter = new FirebaseIndexRecyclerAdapter<Chat, ChatHolder>(
Chat.class,
android.R.layout.two_line_list_item,
ChatHolder.class, mIndexRef,
mDataRef) {
#Override
public void populateViewHolder(ChatHolder chatMessageViewHolder, Chat chatMessage, int position) {
chatMessageViewHolder.setName(chatMessage.getName());
chatMessageViewHolder.setText(chatMessage.getText());
}
};
recycler.setAdapter(mAdapter);
Related
i have a recyclerview with hidden items under condition and it works great but when i scroll the recyclerview it keeps scrolling an empty page after i scroll all the data included here is my code
adapter
#Override
public void onBindViewHolder(#NonNull ViewHolder holder, int position) {
holder.id.setText(mData.get(position).getId());
holder.date.setText(mData.get(position).getDate());
holder.itemName.setText(mData.get(position).getItemName());
holder.price.setText(mData.get(position).getPrice());
if (holder.id.getText().toString().equals("")){
holder.itemView.setVisibility(View.GONE);}
else{
holder.itemView.setVisibility(View.VISIBLE);
}
in recyclerview activity
mData.add(new items(num,itemName,price,date,row));
adapter = new Adapter(mData,recyclerViewItems.this);
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
recyclerView.setLayoutManager(linearLayoutManager);
linearLayoutManager.setReverseLayout(false);
linearLayoutManager.setStackFromEnd(false);
recyclerView.setAdapter(adapter);
i want the recyclerview to stop scrolling at the last visible item and i dont know how to do it
please help me
thank you in advance
i hope that you could help me.
i want to use a expandablerecyclerview but i dont need to expand a list of other elements like the lib says
library example
I just need that the item expand and show more info of the item inside the recycler
You can use advanced recyclerview's expandable future
public class ExpandableWithHeaderFooterExampleActivity extends AppCompatActivity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_demo_minimal);
OnListItemClickMessageListener clickListener = new OnListItemClickMessageListener() {
#Override
public void onItemClicked(String message) {
View container = findViewById(R.id.container);
Snackbar.make(container, message, Snackbar.LENGTH_SHORT).show();
}
};
RecyclerView recyclerView = findViewById(R.id.recycler_view);
// Setup expandable feature and RecyclerView
RecyclerViewExpandableItemManager expMgr = new RecyclerViewExpandableItemManager(null);
// Create wrapped adapter: MyItemAdapter -> expMgr.createWrappedAdapter -> MyHeaderFooterAdapter
RecyclerView.Adapter adapter;
adapter = new SimpleDemoExpandableItemAdapter(expMgr, clickListener);
adapter = expMgr.createWrappedAdapter(adapter);
adapter = new DemoHeaderFooterAdapter(adapter, clickListener);
recyclerView.setAdapter(adapter);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
// NOTE: need to disable change animations to ripple effect work properly
((SimpleItemAnimator) recyclerView.getItemAnimator()).setSupportsChangeAnimations(false);
expMgr.attachRecyclerView(recyclerView);
}
}
In my Activity, I use a RecyclerView that uses a FirebaseRecyclerAdapter to draw a list:
mChatDetailsAdapter = new ChatDetailsAdapter(
this,
MessageData.class,
R.layout.layout_chat_item,
ChatDetailsAdapter.MessageViewHolder.class,
query);
mChatListView.setHasFixedSize(true);
LinearLayoutManager lLinearLayoutManager = new LinearLayoutManager(ChatDetailsActivity.this, LinearLayoutManager.VERTICAL, false);
lLinearLayoutManager.setStackFromEnd(true);
lLinearLayoutManager.setReverseLayout(true);
mChatListView.setLayoutManager(lLinearLayoutManager);
mChatListView.addItemDecoration(new VerticalSpaceItemDecoration(UIUtils.dpToPx(ChatDetailsActivity.this, 8)));
mChatListView.setAdapter(mChatDetailsAdapter);
The Adapter takes care about the views:
#Override
protected void populateViewHolder(final MessageViewHolder pViewHolder, final MessageData pMessageData, int pPosition) {
pViewHolder.mMessageTextView.setText(pMessageData.getMessage());
pViewHolder.mSelfLinearLayout.setVisibility(View.VISIBLE);
pViewHolder.mTimeTExtView.setText(StringUtils.toMessageTimeString(mContext, pMessageData.getTime()));
}
In the onBindViewHolder() method I basically do the same, be assigning the data from the model (works correctly after looking at the log messages). Now when scrolling the list the RecyclerView changes its values and doesn't recycle correctly and I have no idea why. Any idea?
My recyclerview should open the first item closed. To this end, I wrote these lines.
LinearLayoutManager llm = new LinearLayoutManager(getActivity());
llm.scrollToPosition(1);
paletteRecyclerView.setLayoutManager(llm);
I want to check if it is possible to scroll to position 1 fully. If my recyclerview is small I must open it without closing the first item. How can I check it?
I assume that you want to know if there are items to scroll in RecyclerView. So you can check as below after setting the adapter to the recyclerView.
recyclerView.post(new Runnable() {
#Override
public void run() {
int recyclerViewheight = recyclerView.getHeight();
int totalChildViewsHeight = recyclerView.computeVerticalScrollRange();
if (recyclerViewheight > totalChildViewsHeight) {
//there is no scroll (there are no more items to scroll)
} else {
//there is scroll (there are items to scroll)
}
}
});
Try with below code...
LinearLayoutManager llm = new LinearLayoutManager(getActivity());
recyclerView.setLayoutManager(llm);
RecyclerView.Adapter adapter = new YourAdapter();
recyclerView.setAdapter(adapter);
recyclerView.scrollToPosition(position);
I am trying to use RecyclerView to create a chat application. I am using a LinearLayoutManager with setReverseLayout(true).
When I am scrolled all the way to the bottom (which is the dataset start = newest message) and a new message is inserted into the dataset, the item appears at the bottom of the list as expected (the view is scrolled up to make room for the new item).
The problem I have is when I have scrolled up to see the older messages. When a new message is inserted to the beginning of the dataset, the view is scrolled up by approximately one message height, even though that message isn't even rendered since it's out of the viewport's range.
How can I keep the scrolling behavior, when the view is scrolled to the bottom, but disable it when I have scrolled to the older messages?
UPDATE:
I also made a small app, where this problem is reproduced:
https://github.com/ehehhh/RecyclerViewProblem
UPDATE 2: I committed the fix that worked to the repo I made as well.
Relevant code (hopefully):
compile 'com.android.support:recyclerview-v7:24.2.0'
XML:
<android.support.v7.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipToPadding="false"
android:paddingBottom="8dp"
android:paddingTop="8dp"
app:layout_behavior="#string/appbar_scrolling_view_behavior"/>
RecyclerView init code:
layoutManager = new LinearLayoutManager(context);
layoutManager.setOrientation(LinearLayoutManager.VERTICAL);
layoutManager.setReverseLayout(true);
recyclerView.setLayoutManager(layoutManager);
recyclerView.setScrollContainer(true);
recyclerView.setLayoutAnimation(null);
recyclerView.setItemAnimator(null);
adapter = new ChatAdapter(...);
recyclerView.setAdapter(adapter);
Adapter:
public class ChatAdapter extends RecyclerView.Adapter<ChatViewHolder> {
private List<MessageWrapper> dataset;
public ChatAdapter(List<MessageWrapper> dataset, ...) {
this.dataset = dataset;
setHasStableIds(true);
}
...
#Override
public long getItemId(int position) {
return dataset.get(position).getId();
}
#Override
public int getItemCount() {
return dataset.size();
}
public void datasetChanged(List<MessageWrapper> dataset) {
this.dataset = dataset;
notifyDataSetChanged();
}
}
When a new item is added to the dataset, I just call the datasetChanged method in the adapter.
in Recycler view using notifyDataSetChanged is redundant if you know the items changed
you can use
notifyItemInserted(position)
in this particular case what worked was
notifyItemInserted(0);
or
notifyItemRangeInserted(positionStart, newItems.size() - 1)
this will only rebind the views in this range
check
https://developer.android.com/reference/android/support/v7/widget/RecyclerView.Adapter.html#notifyItemInserted(int)
I had a similar issue. I was making chat application, and my RecyclerView was always displaying rows from the top, and I wanted it to go to the bottom to display last inserted message. This is what worked for me, recyclerView.scrollToPosition(messages.size()-1) added in ChildEventListener:
public class MainActivity extends AppCompatActivity {
private RecyclerView recyclerView;
private MessageAdapter mMessageAdapter;
private List<Message> messages;
private FirebaseDatabase mFirebaseDatabase;
private DatabaseReference mMessagesDatabaseRef;
....
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mFirebaseDatabase = FirebaseDatabase.getInstance();
mMessagesDatabaseRef = mFirebaseDatabase.getReference().child("messages");
recyclerView = (RecyclerView) findViewById(R.id.recycler_view);
// Initialize message ListView and its adapter
messages = new ArrayList<>();
mMessageAdapter = new MessageAdapter(messages);
RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(getApplicationContext());
recyclerView.setLayoutManager(mLayoutManager);
recyclerView.setAdapter(mMessageAdapter);
.....
mMessagesDatabaseRef.addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
messages.add(dataSnapshot.getValue(Message.class));
recyclerView.scrollToPosition(messages.size()-1);
mMessageAdapter.notifyDataSetChanged();
}
......
});
}
}