RecyclerView Adapter not updating view content - android

I having a recyclerview with GridLayoutManager, it populating the grid properly but not updating the data.
Below is my code,
public class AppsGridViewAdapter extends RecyclerView.Adapter<AppsGridViewAdapter.GridViewHolder>{
private ArrayList<App> appArrayList;
private Context context;
public AppsGridViewAdapter(Context context,ArrayList<App> appArrayList){
this.appArrayList = appArrayList;
this.context = context;
}
public static class GridViewHolder extends RecyclerView.ViewHolder{
CompoundAppButton compoundAppButton;
public GridViewHolder(CompoundAppButton itemView){
super(itemView);
compoundAppButton = (CompoundAppButton)itemView;
}
}
#Override
public GridViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
CompoundAppButton appButton = new CompoundAppButton(context,null);
return new GridViewHolder(appButton);
}
#Override
public void onBindViewHolder(GridViewHolder holder, int position) {
App app = appArrayList.get(position);
holder.compoundAppButton.updateButtonConfig(app);
}
#Override
public int getItemCount() {
return appArrayList.size();
}
}
Having valid values in the list, but not updating. Where CustomAppButton is a customview. Anyone can help me why it doesnt update.
UPDATE:
I calling recyclerview from my activity, below is the specific code
recyclerView = (RecyclerView)findViewById(R.id.recycler_view);
recyclerView.addItemDecoration(new MarginDecoration(this));
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new GridLayoutManager(this, 3));
AppsGridViewAdapter adapter = new AppsGridViewAdapter(this,appList);
recyclerView.setAdapter(adapter);
The activity contains only recyclerview.
updateButtonConfig is a function in CustomAppButton class, this is where view is updated. getting data to this function, have checked the log.
public void updateButtonConfig(App app){
Picasso.with(context)
.load(app.getAppIcon())
.placeholder(R.drawable.app_icon)
.into(appIcon);
appName.setText(app.getAppName());
category.setText(app.getAppCategory());
price.setText(app.getAppPrice());
appPackage = app.getAppPackage();
}

Related

RecyclerView lags when I use the scrollbar when there is a large amount of data

My RecyclerAdapter
public class CollatzAdapter extends RecyclerView.Adapter<CollatzAdapter.ViewHolder> {
ArrayList<BigInteger> list = new ArrayList<BigInteger>();
List<Long> primeList;
public CollatzAdapter() {
}
public CollatzAdapter(ArrayList<BigInteger> list, ArrayList<Long> primeList) {
this.list = list;
this.primeList = primeList;
}
public CollatzAdapter(ArrayList<BigInteger> list) {
this.list = list;
}
#NonNull
#Override
public CollatzAdapter.ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.row,parent,false);
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull CollatzAdapter.ViewHolder holder, int position) {
holder.mIterationPosition.setText((position + ":"));
holder.mNumber.setText(list.get(position).toString());
}
#Override
public int getItemCount() {
return list.size();
}
public class ViewHolder extends RecyclerView.ViewHolder {
public TextView mNumber;
public TextView mIterationPosition;
public ViewHolder(#NonNull View itemView) {
super(itemView);
mNumber = itemView.findViewById(R.id.iteration_num);
mIterationPosition = itemView.findViewById(R.id.iteration_position);
//mPrime = itemView.findViewById(R.id.iteration_prime);
}
}
public void setList(ArrayList<BigInteger> list) {
this.list = list;
}
}
Where I Implement
iterationFragment = inflater.inflate(R.layout.fragment_iteration, container, false);
collatzViewModel = new ViewModelProvider(getActivity()).get(CollatzViewModel.class);
mRecyclerView = (RecyclerView) iterationFragment.findViewById(R.id.recycler_view);
mRecyclerView.setHasFixedSize(false);
mLayoutManager = new LinearLayoutManager(getActivity());
mAdapter = new CollatzAdapter();
mRecyclerView.setLayoutManager(mLayoutManager);
mRecyclerView.setAdapter(mAdapter);
collatzViewModel.getCollatz().observe(getViewLifecycleOwner(),(list)->{
mAdapter.setList(list);
mAdapter.notifyDataSetChanged();
});
When RecyclerView contains large BigIntegers, say 300 characters for one integer and a list 100,000 of them, it lags when I use the scrollbar. Is there a way to prevent it from lagging when I scroll? It lags so much that it crashes the app. I don't understand why this happens since the RecyclerView should only load a couple of BigIntegers.
Repository: https://github.com/ErickSorto/Collatz-Calculator

Make ItemTouchHelper run OnMove only when I release my touch on a RecyclerView List

I have a basic RecyclerView list and added a ItemTouchHelper in order to drag and drop list items.
The problem I have with it is that it runs onMove on every single list item it passes and it's lagging the app real hard.
Is there a way to implement it so that onMove only runs when I release my hold on a RecyclerView list item?
Thanks.
MainActivity.java
public class pillar_sort extends AppCompatActivity {
private MyRecyclerViewAdapter adapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
// Initialize layout
super.onCreate(savedInstanceState);
setContentView(R.layout.pillar_sort);
final SharedPreferences sharedPref = // Get SharedPreferences
final ArrayList<String> modules = // Import a list
final ArrayList<Boolean> visibility = // Import a list
RecyclerView recyclerView = findViewById(R.id.recyclerView);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
adapter = new MyRecyclerViewAdapter(this, modules, visibility, cardcolor, txtcolor);
recyclerView.setAdapter(adapter);
VerticalSpaceItemDecoration decor = new VerticalSpaceItemDecoration();
recyclerView.addItemDecoration(decor);
ItemTouchHelper helper = new ItemTouchHelper(new ItemTouchHelper.SimpleCallback(ItemTouchHelper.UP|ItemTouchHelper.DOWN, 0) {
#Override
public boolean onMove(#NonNull RecyclerView recyclerView, #NonNull RecyclerView.ViewHolder dragged, #NonNull RecyclerView.ViewHolder target) {
int position_dragged = dragged.getAdapterPosition();
int position_target = target.getAdapterPosition();
Collections.swap(modules,position_dragged,position_target);
adapter.notifyItemMoved(position_dragged,position_target);
adapter.notifyDataSetChanged();
return false;
}
#Override
public void onSwiped(#NonNull RecyclerView.ViewHolder viewHolder, int direction) {
}
});
helper.attachToRecyclerView(recyclerView);
}
MyRecyclerViewAdapter.java
public class MyRecyclerViewAdapter extends RecyclerView.Adapter<MyRecyclerViewAdapter.ViewHolder> {
// Variables go here
MyRecyclerViewAdapter( /* a lot of data to pass onto the adapter */ ) {
// get data from MainActivity and put on variables
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = mInflater.inflate(R.layout.recyclerview_row, parent, false);
CardView card = view.findViewById(R.id.card);
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(final ViewHolder holder, final int position){
// Put data to TextViews and set card color
}
#Override
public int getItemCount() {
return modules.size();
}
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
TextView myTextView;
ImageButton image_visibility;
ViewHolder(View itemView) {
super(itemView);
myTextView = itemView.findViewById(R.id.rowText);
image_visibility = itemView.findViewById(R.id.imageButton);
itemView.setOnClickListener(this);
}
#Override
public void onClick(View view) {
}
}

swipe cards with recycle view

This not like question its more like discussion
I'm using swipe cards from this library 'link.fls:swipestack:0.3.0'
With the help of these cards i'm creating recycle view on every card but the data is been repeating for every card
i have used adapter to generate cards and inside this adapter i have initialized recycle view
So my question is how to use recycle view with these swipe cards with non repeating values on every card...
Thanks in advance
Adapter code
public class ParentExamsCardAdapter extends BaseAdapter {
private Context mContext;
private List<ParentExamCards_Pojo> parentExamCardsPojoList = new ArrayList<>();
private RecyclerView recyclerView;
private ParentExamsDataAdapter dataAdapter;
public ParentExamsCardAdapter(Context mContext, List<ParentExamCards_Pojo> parentExamCardsPojoList, ParentExamsDataAdapter dataAdapter) {
this.mContext = mContext;
this.parentExamCardsPojoList = parentExamCardsPojoList;
this.dataAdapter = dataAdapter;
}
#Override
public int getCount() {
return parentExamCardsPojoList.size();
}
#Override
public Object getItem(int i) {
return i;
}
#Override
public long getItemId(int i) {
return i;
}
#Override
public View getView(int position, View view, ViewGroup viewGroup) {
View itemView = LayoutInflater.from(mContext).inflate(R.layout.single_parent_exams_swipecards, viewGroup, false);
ParentExamCards_Pojo pojoCards = parentExamCardsPojoList.get(position);
CardView cardView = itemView.findViewById(R.id.singleParentExamsCards_cardView);
LinearLayout linearLayout = itemView.findViewById(R.id.singleParentExamsCards_linear);
TextView textView_Title = itemView.findViewById(R.id.singleParentExamsCards_txtTitle);
cardView.setBackgroundColor(pojoCards.getColor());
textView_Title.setText(pojoCards.getExamname());
recyclerView = itemView.findViewById(R.id.singleParentExamsCards_recycleView);
RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(mContext);
recyclerView.setLayoutManager(layoutManager);
recyclerView.setItemAnimator(new DefaultItemAnimator());
recyclerView.addItemDecoration(new DividerItemDecoration(mContext, LinearLayoutManager.VERTICAL));
recyclerView.setAdapter(dataAdapter);
return itemView;
}
#Override
public int getItemViewType(int position) {
return position;
}
}
ParentExamsDataAdapter
public class ParentExamsDataAdapter extends RecyclerView.Adapter<ParentExamsDataAdapter.MyViewHolder>{
private Context mContext;
private List<List<ParentExams_Pojo>> parentExamsPojoDataList = new ArrayList<>();
public ParentExamsDataAdapter(Context mContext, List<List<ParentExams_Pojo>> parentExamsPojoDataList) {
this.mContext = mContext;
this.parentExamsPojoDataList = parentExamsPojoDataList;
}
public class MyViewHolder extends RecyclerView.ViewHolder {
TextView textView_name;
TextView textView_date;
TextView textView_time;
public MyViewHolder(View itemView) {
super(itemView);
textView_name=itemView.findViewById(R.id.singleParentExamsData_txtName);
textView_date=itemView.findViewById(R.id.singleParentExamsData_txtDate);
textView_time=itemView.findViewById(R.id.singleParentExamsData_txtTime);
}
}
#Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(mContext).inflate(R.layout.single_parent_exams_data, parent, false);
return new MyViewHolder(view);
}
#Override
public void onBindViewHolder(MyViewHolder holder, int position) {
ParentExams_Pojo pojoData=parentExamsPojoDataList.get(position).get(position);
holder.textView_name.setText(pojoData.getSubjectname()+"-"+pojoData.getSubjectaspectname());
holder.textView_date.setText(pojoData.getExamdate());
holder.textView_time.setText(pojoData.getStarttime());
}
#Override
public int getItemCount() {
return parentExamsPojoDataList.size();
}
}
Basically You have to Set different adapter(ParentExamsDataAdapter(exams[position].getmarks)) inside the getview() method of ParentExamCardAdapter. The problem here is you are sending one instance of adapter to your parent adapter from Activity or Fragment I guess. And you are setting this for every CardAdapter.
Edit:
Adding suggested code changes from the comments to the answer.
RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(mContext);
recyclerView.setLayoutManager(layoutManager);
recyclerView.setItemAnimator(new DefaultItemAnimator());
recyclerView.addItemDecoration(new DividerItemDecoration(mContext, LinearLayoutManager.VERTICAL));
recyclerView.setAdapter(new ParentExamsDataAdapter(**list of items**));
found the solution your are passing same adapter to every recyclerview in every card that is one reason for your problem in ParentExamsCardAdapter
recyclerView.setAdapter(dataAdapter);
the data adapter is same for every postion
the arraylist value is same for aa recyclerview
pass List List ParentExams_Pojo arraylist to ParentExamsCardAdapter use its size in getItemCount
then in onbindviewholder use the arraylist.get(position) to pass to adapter then in adapter use List ParentExams_Pojo to get the list and its size in getitemcount it will solve i think
thus you will have only 1 positon in the adapyter
ParentExams_Pojo pojoData=parentExamsPojoDataList.get(position)

RecyclerView onCreateViewHolder not called

RecyclerView setAdapter do but calling method ChatAdapter, registerAdapterDataObserver, onAttachedToRecyclerView, getItemCount 5 calling
xml layout_height is match_parent
getItemCount is 5 not null, but onCreateViewHolder is not called.
MyActivity.java:
List<ChatMessage> messages = new ArrayList<ChatMessage>();
LinearLayoutManager layoutManager = new LinearLayoutManager(getApplicationContext());
reyclerview_message_list.setAdapter(new ChatAdapter(messages, R.layout.chat_send));
reyclerview_message_list.setLayoutManager(new LinearLayoutManager(this));
reyclerview_message_list.setItemAnimator(new DefaultItemAnimator());
reyclerview_message_list.addItemDecoration(new DividerItemDecoration(getApplicationContext(), layoutManager.getOrientation()));
Adapter.java:
public class ChatAdapter extends RecyclerView.Adapter<ChatAdapter.ViewHolder> {
private List<ChatMessage> itemList;
private int itemLayout;
public ChatAdapter(List<ChatMessage> items, int itemLayout){
this.itemList = items;
this.itemLayout = itemLayout;
}
#Override
public ChatAdapter.ViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
View view = LayoutInflater.from(viewGroup.getContext()).inflate(itemLayout, viewGroup, false);
return new ChatAdapter.ViewHolder(view);
}
#Override
public void onBindViewHolder(ChatAdapter.ViewHolder viewholder, int position) {
ChatMessage item = itemList.get(position);
viewholder.messageBody.setText(item.getMessageBody());
viewholder.messageTime.setText(item.getMessageTime());
viewholder.messageState.setText(item.getMessageState());
viewholder.itemView.setTag(item);
}
public class ViewHolder extends RecyclerView.ViewHolder {
public TextView messageBody, messageTime, messageState;
public ViewHolder(View itemView) {
super(itemView);
messageBody = (TextView)itemView.findViewById(R.id.text_message_body);
messageTime= (TextView)itemView.findViewById(R.id.text_message_time);
messageState= (TextView)itemView.findViewById(R.id.text_message_state);
}
}
#Override
public int getItemCount() {
return itemList.size();
}
Why is onCreateViewHolder not called?
I just update your Adapter code and its working well.
public class ChatAdapter extends RecyclerView.Adapter<ChatAdapter.ViewHolder> {
private List<ChatMessage> itemList;
private int itemLayout;
private Context mContext;
public ChatAdapter(List<ChatMessage> items, int itemLayout, Context context){
this.itemList = items;
this.itemLayout = itemLayout;
this.mContext = context;
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
View view = LayoutInflater.from(mContext).inflate(itemLayout, viewGroup, false);
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(ViewHolder viewholder, int position) {
ChatMessage item = itemList.get(position);
viewholder.messageBody.setText(item.getMessageBody());
viewholder.messageTime.setText(item.getMessageTime());
viewholder.messageState.setText(item.getMessageState());
viewholder.itemView.setTag(item);
}
public class ViewHolder extends RecyclerView.ViewHolder {
public TextView messageBody, messageTime, messageState;
public ViewHolder(View itemView) {
super(itemView);
messageBody = (TextView)itemView.findViewById(R.id.text_message_body);
messageTime= (TextView)itemView.findViewById(R.id.text_message_time);
messageState= (TextView)itemView.findViewById(R.id.text_message_state);
}
}
#Override
public int getItemCount() {
return itemList.size();
}
}
And you Activity or Fragment first get the RecyclerView and then set adapter like this:
RecyclerView reyclerview_message_list = findViewById(R.id.recyclerView);
reyclerview_message_list.setAdapter(new ChatAdapter(messages, R.layout.list_row, this)); // passed another parameter Context
reyclerview_message_list.setLayoutManager(new LinearLayoutManager(this));
reyclerview_message_list.setItemAnimator(new DefaultItemAnimator());
reyclerview_message_list.addItemDecoration(new DividerItemDecoration(getApplicationContext(), layoutManager.getOrientation()));
Hope this will solve your problem.
You didn't notify your adapter after setting the value. While you setting the adapter messages is empty. When you adding the value in messages using addAll(message_objects) those data are added in ArrayList but you have to notify the adapter using notifyDataSetChanged(). Declare your adapter in class level then create object of adapter before setting the adapter in recyclerview and notify the adapter after you added objects in ArrayList.
private ChatAdapter chatAdapter;//declare it globally(class level)
chatAdapter = new ChatAdapter(messages, R.layout.chat_send);
reyclerview_message_list.setAdapter(chatAdapter);
reyclerview_message_list.setLayoutManager(new LinearLayoutManager(this));
reyclerview_message_list.setItemAnimator(new DefaultItemAnimator());
reyclerview_message_list.addItemDecoration(new DividerItemDecoration(getApplicationContext(), layoutManager.getOrientation()));
messages.addAll(ChatMessage_Objects_you_getting_from_web_service);
chatAdapter.notifyDataSetChanged();

RecylerView Adapter Override methods not being called

public class HashTagSearchAdapter extends RecyclerView.Adapter<HashTagSearchAdapter.HashTagViewHolder> {
Context context;
List<TagSearchObject> tagResponses;
public HashTagSearchAdapter (Context context, List<TagSearchObject> tagResponses){
this.context = context;
this.tagResponses = tagResponses;
for (int i =0;i<tagResponses.size();i++){
Log.e("tagfor",tagResponses.get(i).toString());
}
Log.e("constructor",tagResponses.size()+"");
Log.e("constructor","here");
}
#Override
public HashTagViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(context).inflate(R.layout.tag_search_list,parent,false);
Log.e("onCreate","here");
return new HashTagViewHolder(view);
}
#Override
public void onBindViewHolder(HashTagViewHolder holder, int position) {
TagSearchObject userTagResponse = tagResponses.get(position);
Log.e("tag",userTagResponse.toString());
holder.name.setText(userTagResponse.getName());
holder.count.setText(userTagResponse.getChallengeCount()+" public posts");
}
#Override
public int getItemCount() {
Log.e("getItemCount",this.tagResponses.size()+"");
return tagResponses.size();
}
class HashTagViewHolder extends RecyclerView.ViewHolder{
ImageView hashtag;
TextView name,count;
public HashTagViewHolder(View itemView) {
super(itemView);
name = (TextView) itemView.findViewById(R.id.name);
count = (TextView) itemView.findViewById(R.id.count);
}
}
}
here logcat is :
E/tagfor:TagSearchObject{id='1', name='hahah', challengeCount='1'}
E/constructor: 1
E/constructor: here
Because you have not added a layout manager and/or your recycler view is not visible. Since it's not visible, no attempt to draw is made and itemCount is never called because, well, there is nothing to draw.
set layout manager before setAdapter to the RecyclerView
LinearLayoutManager llm = new LinearLayoutManager(getApplicationContext());
HashTagSearchAdapter hashTagSearchAdapter = new
HashTagSearchAdapter(context,tagSearchObjects);
recyclerView.setLayoutManager(llm);
recyclerView.setAdapter(hashTagSearchAdapter);

Categories

Resources