RecyclerView onCreateViewHolder not called - android

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

Related

Android notifyDataSetChanged for nested Adapter doesn't work

In my SectionsListAdapter adapter i have nested Adapter named MonthLessonsList, after get date from web service and set new data and call notifyDataSetChanged method for adapter, main adapter as SectionsListAdapter can be refresh, but nested adapter dont refresh and after calling notifyDataSetChanged for that, doesn't work correctly and don't show new data
call and set new data from Fragment:
monthSectionsItems = SQLite.select().from(MonthSections.class).queryList();
adapter.setData(monthSectionsItems);
and my Adapter with nested adapter:
public class SectionsListAdapter extends RecyclerView.Adapter<SectionsListAdapter.MyViewHolder> {
private final OnItemSelected listener;
private List<MonthSections> list;
private Context context;
private MonthLessonsList lessonsListAdapter;
public SectionsListAdapter(List<MonthSections> followingsList, Context mContext, OnItemSelected listener) {
this.list = followingsList;
this.context = mContext;
this.listener = listener;
}
#Override
public MyViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.sections_list_row, parent, false);
return new MyViewHolder(itemView);
}
#Override
public void onBindViewHolder(#NonNull final MyViewHolder holder, final int position) {
holder.indicatorIcon.setText(list.get(position).getSection_month_name());
...
List<SectionLesson> lessonsList = list.get(position).getLessons();
lessonsListAdapter = new MonthLessonsList(lessonsList);
RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(context);
holder.userChildCategories.setLayoutManager(mLayoutManager);
holder.userChildCategories.setAdapter(lessonsListAdapter);
...
}
#Override
public int getItemCount() {
return list.size();
}
public void setData(List<MonthSections> data) {
list.clear();
list.addAll(data);
notifyDataSetChanged();
lessonsListAdapter.notifyDataSetChanged();
}
public List<MonthSections> getData() {
return list;
}
class MyViewHolder extends RecyclerView.ViewHolder {
...
public MyViewHolder(View view) {
super(view);
ButterKnife.bind(this, view);
section_title.setGravity(Gravity.RIGHT);
}
}
public class MonthLessonsList extends RecyclerView.Adapter<MonthLessonsList.LessonsViewHolder> {
private List<SectionLesson> lessonItem;
public class LessonsViewHolder extends RecyclerView.ViewHolder {
public TextView title;
public LessonsViewHolder(View view) {
super(view);
title = view.findViewById(R.id.title);
}
}
public MonthLessonsList(List<SectionLesson> lists) {
this.lessonItem = lists;
}
#Override
public LessonsViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.child_list_row, parent, false);
return new LessonsViewHolder(itemView);
}
#SuppressLint("SetTextI18n")
#Override
public void onBindViewHolder(#NonNull LessonsViewHolder holder, int position) {
SectionLesson lesson = lessonItem.get(position);
holder.title.setText("درس: " + (position + 1) + ") " + lesson.getTitle());
}
#Override
public int getItemCount() {
return lessonItem.size();
}
}
}
Declare child adapter inside onBindViewHolder, and remove from global level.
And no need to notify child adapter. Because that will be automatically filled when parent onBindViewHolder is called.
Like
MonthLessonsList lessonsListAdapter = new MonthLessonsList(lessonsList);
holder.userChildCategories.setAdapter(lessonsListAdapter);

Android RecyclerView does not update on data changed

The RecyclerView shows only items that was in ArrayList (data of the adapter) on creation. All my attempts to add more lines seems to work, but the list stays with initial data.
It isn't duplicate, as I tried all the suggestions found on google.
What I already did:
adapter.notifyDataSetChanged();
adapter.notifyItemChanged(5);
recycleList.invalidate();
recycleList.setAdapter(adapter);
running the update on UIThread with Handler
The adapter work as it should - onCreateView do it's work (creat new lines) as well as onBindView (bind new data). getItemCount() returns correct value (larger after update). Everything looks like it should be - instead of the final view - does not change.
The only thing that will work is recreate the adapter from scratch with new dataset - completely unacceptable by design (ugly on long lists).
Here is the code:
Create in fragment:
adapter = new MyListAdapter(getContext());
adapter.addItems(initialItems); // These and only these I see on the list
LinearLayoutManager mLayoutManager=new LinearLayoutManager(getContext());
recycleList.setLayoutManager(mLayoutManager);
recycleList.setAdapter(adapter);
Trying to update from fragment:
public void onUpdateReady(ArrayList<Model> freshData) {
new Handler(Looper.getMainLooper()).post(new Runnable() {
#Override
public void run() { // UI thread
adapter.addItems(freshData);
adapter.notifyDataSetChanged();
adapter.notifyItemChanged(5);
recycleList.invalidate();
//notifyItemRangeInserted(3,freshData.size());
}
});
}
Adapter:
private Context mContext;
private ArrayList<Model> data;
public MyListAdapter(Context mContext) {
this.mContext = mContext;
data=new ArrayList<>();
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
LayoutInflater inflater = LayoutInflater.from(mContext);
View view = inflater.inflate(R.layout.list_item, parent, false);
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(ViewHolder viewHolder, int position) {
viewHolder.textName.setText(data.get(position).getName());
}
#Override
public int getItemCount() {
return data.size();
}
public void addItems(Collection<Model> list) {
data.addAll(list);
}
public class ViewHolder extends RecyclerView.ViewHolder {
#BindView(R.id.textName) TextView textName;
public ViewHolder(View itemView) {
super(itemView);
ButterKnife.bind(this,itemView);
}
}
UPDATE: Changed according to comments:
public void addItems(Collection<Model> list) {
ArrayList<Model> newData=new ArrayList<>(); // Make new array
newData.addAll(data); // Take old
newData.addAll(list); // Add new
data=newData; // change to data to newly created array
notifyDataSetChanged();
}
try this
In Fragment
ArrayList<Data> items=new ArrayList<>();
items.addAll(initialItems);
adapter = new MyListAdapter(getContext(),items);
LinearLayoutManager mLayoutManager=new LinearLayoutManager(getContext());
recycleList.setLayoutManager(mLayoutManager);
recycleList.setAdapter(adapter);
public void onUpdateReady(ArrayList<Model> freshData) {
new Handler(Looper.getMainLooper()).post(new Runnable() {
#Override
public void run() { // UI thread
items.addAll(freshData);
adapter.notifyDataSetChanged();
followList.invalidate();
}
});
}
private Context mContext;
private ArrayList<Model> data;
public MyListAdapter(Context mContext,ArrayList<Model> data) {
this.mContext = mContext;
this.data=data;
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
LayoutInflater inflater = LayoutInflater.from(mContext);
View view = inflater.inflate(R.layout.list_item, parent, false);
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(ViewHolder viewHolder, int position) {
viewHolder.textName.setText(data.get(position).getName());
}
#Override
public int getItemCount() {
return data.size();
}
public class ViewHolder extends RecyclerView.ViewHolder {
#BindView(R.id.textName) TextView textName;
public ViewHolder(View itemView) {
super(itemView);
ButterKnife.bind(this,itemView);
}
}
Change your Adapter constructor:
private ArrayList<Model> data;
public MyListAdapter(Context mContext,ArrayList<Model> data) {
this.mContext = mContext;
this.data = data;}
public void addItems(Collection<Model> list) {
data.addAll(list);
}
fragment:
adapter = new MyListAdapter(getContext(),initialItems);
I had a similar problem once and calling invalidateViews on the ListView worked, even if it was a hack. Instead of recycleList.invalidate(); try recycleList.invalidateViews();

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

RecyclerView-: No adapter attached; skipping layout

I have been reading the different answers here on stackoverflow post and tried to implement their solutions but I am still getting the error
public class Appetizer extends AppCompatActivity {
private RecyclerView recyclerView;
private AdapterFood mAdapter;
recyclerView = (RecyclerView)findViewById(R.id.lvaptzr);
mAdapter = new AdapterFood(Appetizer.this,data);
recyclerView.setAdapter(mAdapter);
recyclerView.setLayoutManager(new LinearLayoutManager(Appetizer.this));
this is my Adapter class:
public class AdapterFood extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private Context context;
private LayoutInflater inflater;
List<DataFood> data = Collections.emptyList();
DataFood current;
int currentPos=0;
public AdapterFood(Context context, List<DataFood> data){
this.context=context;
inflater=LayoutInflater.from(context);
this.data=data;
}
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view=inflater.inflate(R.layout.list_item,parent,false);
Myholder holder=new Myholder(view);
return holder;
}
#Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
Myholder myholder=(Myholder) holder;
DataFood current=data.get(position);
myholder.textFoodname.setText(current.foodName);
myholder.textPrice.setText("Rp. " + current.price);
myholder.textId.setText(current.foodId);
Glide.with(context).load("http://kelompokdua.hol.es/pic/" + current.foodImage)
.placeholder(R.mipmap.ic_launcher)
.error(R.mipmap.ic_launcher)
.into(myholder.ivFood);
}
#Override
public int getItemCount() {
return data.size();
}
class Myholder extends RecyclerView.ViewHolder{
TextView textFoodname,textPrice,textId;
ImageView ivFood;
public Myholder(View itemView) {
super(itemView);
textFoodname=(TextView) itemView.findViewById(R.id.textFoodname);
ivFood=(ImageView)itemView.findViewById(R.id.ivFood);
textId=(TextView)itemView.findViewById(R.id.textid);
textPrice=(TextView) itemView.findViewById(R.id.textPrice);
}
}
}
i try any method, but i can't solve the probems. what i am doing wrong?
You should call setLayoutManager before setAdapter .
recyclerView = (RecyclerView)findViewById(R.id.lvaptzr);
LinearLayoutManager mLayoutManager = new LinearLayoutManager(Appetizer.this);
recyclerView.setLayoutManager(mLayoutManager); // 1st
mAdapter= new AdapterFood(Appetizer.this,data);
recyclerView.setAdapter(mAdapter); // 2nd

RecyclerView Adapter not updating view content

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

Categories

Resources