Android notifyDataSetChanged for nested Adapter doesn't work - android

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

Related

How to show all items of list in recyclerview?

I have an adapter that is showing limited Items on Fragment.
#Override
public int getItemCount() {
int limit = 7;
return Math.min(latestProductModelList.size(),limit);
}
and I want to show all the items of list in recyclerview when I click on ViewAll button using the same adapter on another acitivity.
this is my adapter.
`
public class LatestProductAdapter extends RecyclerView.Adapter<LatestProductAdapter.ViewHolder> {
List<LatestProductModel> latestProductModelList = new ArrayList<>();
Context context;
LatestProductClickInterface latestProductClickInterface;
public LatestProductAdapter(Context context, LatestProductClickInterface latestProductClickInterface) {
this.context = context;
this.latestProductClickInterface = latestProductClickInterface;
}
#NonNull
#Override
public ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(context).inflate(R.layout.item_layout,parent,false);
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull ViewHolder holder, int position) {
LatestProductModel latestProductModel = latestProductModelList.get(position);
Glide.with(context).load(latestProductModel.getImage()).into(holder.itemImage);
holder.itemTitle.setText(latestProductModel.getTitle());
holder.itemView.setOnClickListener(v -> {
latestProductClickInterface.OnLatestProductClicked(latestProductModelList.get(position));
});
}
#Override
public int getItemCount() {
int limit = 7;
return Math.min(latestProductModelList.size(),limit);
}
#SuppressLint("NotifyDataSetChanged")
public void updateList(List<LatestProductModel> latestProductModels){
latestProductModelList.clear();
latestProductModelList.addAll(latestProductModels);
Collections.reverse(latestProductModelList);
notifyDataSetChanged();
}
public static class ViewHolder extends RecyclerView.ViewHolder {
ImageView itemImage;
TextView itemTitle;
public ViewHolder(#NonNull View itemView) {
super(itemView);
itemImage = itemView.findViewById(R.id.item_img);
itemTitle = itemView.findViewById(R.id.item_title);
}
}
}
`
How to achieve this?
Or is there another way to achieve this?
kindly help me.
You can use bellow codes for your adapter:
public class LatestProductAdapter extends RecyclerView.Adapter<LatestProductAdapter.ViewHolder> {
List<LatestProductModel> latestProductModelList = new ArrayList<>();
Context context;
LatestProductClickInterface latestProductClickInterface;
private boolean shouldShowAllItems;
public LatestProductAdapter(Context context, LatestProductClickInterface latestProductClickInterface , boolean shouldShowAllItems) {
this.context = context;
this.latestProductClickInterface = latestProductClickInterface;
this.shouldShowAllItems = shouldShowAllItems;
}
#NonNull
#Override
public ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(context).inflate(R.layout.item_layout,parent,false);
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull ViewHolder holder, int position) {
LatestProductModel latestProductModel = latestProductModelList.get(position);
Glide.with(context).load(latestProductModel.getImage()).into(holder.itemImage);
holder.itemTitle.setText(latestProductModel.getTitle());
holder.itemView.setOnClickListener(v -> {
latestProductClickInterface.OnLatestProductClicked(latestProductModelList.get(position));
});
}
#Override
public int getItemCount() {
if (shouldShowAllItems){
return latestProductModelList.size();
}else {
int limit = 7;
return Math.min(latestProductModelList.size(), limit);
}
}
#SuppressLint("NotifyDataSetChanged")
public void updateList(List<LatestProductModel> latestProductModels){
latestProductModelList.clear();
latestProductModelList.addAll(latestProductModels);
Collections.reverse(latestProductModelList);
notifyDataSetChanged();
}
public static class ViewHolder extends RecyclerView.ViewHolder {
ImageView itemImage;
TextView itemTitle;
public ViewHolder(#NonNull View itemView) {
super(itemView);
itemImage = itemView.findViewById(R.id.item_img);
itemTitle = itemView.findViewById(R.id.item_title);
}
}
}
and create adapter object accourding your need:
LatestProductAdapter latestProductAdapter = LatestProductAdapter(context , this ,//true or false);

Android Nested Recylcerview with different items counts

I have a nested recyclerview, and I just want it to display different item numbers for each item of the parent recyclerview.
It's supposed that each item implements number of view according to each model object list that's been passed to adapter
It may look like as the layout shown in this image
Here is my parent adapter code
public class ConstructionAdapter extends RecyclerView.Adapter<ConstructionAdapter.ConstructionViewHolder> {
private RecyclerView.RecycledViewPool viewPool = new RecyclerView.RecycledViewPool();
private final List<ConstructionModel> constructionList;
public ConstructionAdapter(List<ConstructionModel> constructionList) {
this.constructionList = constructionList;
}
#NonNull
#Override
public ConstructionViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.construction_cranes_view_item, parent, false);
return new ConstructionViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull ConstructionViewHolder holder, int position) {
holder.setContent(constructionList.get(position));
}
#Override
public int getItemCount() {
return constructionList.size();
}
public class ConstructionViewHolder extends RecyclerView.ViewHolder {
private TextView categoeyTitleTV;
private RecyclerView constructionRecyclerView;
private ConstructionViewHolder(#NonNull View itemView) {
super(itemView);
categoeyTitleTV = itemView.findViewById(R.id.category_title_tv);
constructionRecyclerView = itemView.findViewById(R.id.construction_item_recycler);
}
private void setContent(ConstructionModel model) {
LinearLayoutManager layoutManager = new LinearLayoutManager(itemView.getContext());
constructionRecyclerView.setLayoutManager(layoutManager);
categoeyTitleTV.setText(model.getCraneCategory());
layoutManager.setInitialPrefetchItemCount(model.getSubCategoryList().size());
IndustrialCranesAdapter subCatAdapter = new IndustrialCranesAdapter(model.getSubCategoryList());
constructionRecyclerView.setAdapter(subCatAdapter);
constructionRecyclerView.setRecycledViewPool(viewPool);
}
}
}
Here is my Inner recyclerview adapter
public class IndustrialCranesAdapter extends RecyclerView.Adapter<IndustrialCranesAdapter.IndustrialCranesViewHolder> {
private final List<Crane> industrialCranesList;
public IndustrialCranesAdapter(List<Crane> industrialCranesList) {
this.industrialCranesList = industrialCranesList;
}
#NonNull
#Override
public IndustrialCranesViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.crane_item, parent, false);
return new IndustrialCranesViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull IndustrialCranesViewHolder holder, int position) {
holder.setCranesItems(industrialCranesList.get(position));
}
#Override
public int getItemCount() {
return industrialCranesList.size();
}
public class IndustrialCranesViewHolder extends RecyclerView.ViewHolder {
private TextView craneTitle;
private ImageView craneImage;
private IndustrialCranesViewHolder(#NonNull View itemView) {
super(itemView);
craneTitle = itemView.findViewById(R.id.industrial_crane_title);
craneImage = itemView.findViewById(R.id.industrial_crane_image_view);
itemView.getRootView().setOnClickListener(v->{
Toast.makeText(itemView.getContext(), "Clicked", Toast.LENGTH_SHORT).show();
});
}
private void setCranesItems(Crane crane){
craneTitle.setText(crane.getCraneTitle());
craneImage.setImageResource(crane.getCraneImage());
}
}
}

How to use same adapter in two activity in different ways

Is it possible to call same adapter in two activity for different different work
Here is my RecyclerAdapter:
Only difference when calling from two activity is in this line: From Activity1.java it is:
holder.Name.setText(arrayList.get(position).getName());
And from Activity2.java
holder.Name.setText(arrayList.get(position).getVehicle());
All other code is same how can I use same adapter for different different work.
public class RecyclerAdapter extends RecyclerView.Adapter<RecyclerAdapter.MyViewHolder> {
private ArrayList<Contact> arrayList= new ArrayList<>();
public RecyclerAdapter(ArrayList<Contact> arrayList){
this.arrayList= arrayList;
}
#Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view= LayoutInflater.from(parent.getContext()).inflate(R.layout.item_view,parent,false);
return new MyViewHolder(view);
}
#Override
public void onBindViewHolder (MyViewHolder holder, int position) {
holder.Name.setText(arrayList.get(position).getName());
int sync_status = arrayList.get(position).getSync_status();
if(sync_status== DbContact.SYNC_STATUS_OK){
holder.Sync_Status.setImageResource(R.drawable.success);
}
else {
holder.Sync_Status.setImageResource(R.drawable.stopwatch);
}
}
#Override
public int getItemCount() {
return arrayList.size();
}
public static class MyViewHolder extends RecyclerView.ViewHolder{
ImageView Sync_Status;
TextView Name;
public MyViewHolder(View itemView) {
super(itemView);
Sync_Status=(ImageView)itemView.findViewById(R.id.imgSync);
Name=(TextView)itemView.findViewById(R.id.txtName);
}
}
}
public class RecyclerAdapter extends RecyclerView.Adapter<RecyclerAdapter.MyViewHolder> {
private ArrayList<Contact> arrayList= new ArrayList<>();
private int whichActivity;
public RecyclerAdapter(ArrayList<Contact> arrayList, int activity){
whichActivity = activity;
this.arrayList= arrayList;
}
#Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view= LayoutInflater.from(parent.getContext()).inflate(R.layout.item_view,parent,false);
return new MyViewHolder(view);
}
#Override
public void onBindViewHolder (MyViewHolder holder, int position) {
if(whichActivity == 0) {
holder.Name.setText(arrayList.get(position).getName());
}
else {
holder.Name.setText(arrayList.get(position).getVehicle());
}
int sync_status = arrayList.get(position).getSync_status();
if(sync_status== DbContact.SYNC_STATUS_OK){
holder.Sync_Status.setImageResource(R.drawable.success);
}
else {
holder.Sync_Status.setImageResource(R.drawable.stopwatch);
}
}
#Override
public int getItemCount() {
return arrayList.size();
}
public static class MyViewHolder extends RecyclerView.ViewHolder{
ImageView Sync_Status;
TextView Name;
public MyViewHolder(View itemView) {
super(itemView);
Sync_Status=(ImageView)itemView.findViewById(R.id.imgSync);
Name=(TextView)itemView.findViewById(R.id.txtName);
}
}
}
Try this code. Now when you create your RecyclerAdapter in Activity1 call new RecyclerAdapter(arrayList, 0) and when you create your RecyclerAdapter in Activity2 call new RecyclerAdapter(arrayList, 1). You are just passing a variable into the constructor so your adapter knows which activity it is in and can run through different logic depending on the activity.

Refreshing values of recyclerview adapter from another adapter

I have to two data sets with different adapters inside a single activity and I want to use notifyDataSetChanged() however its not working for the other adapter. So inside my adapterFirst class I have LongCLickListener which is using notifyDataSetChanged() and I want to call the adapterSecond to notify too if adapterFirst is updated. The AdapterSecond data is not being updated when pressing LongClick
public class AdapterFirst extends RecyclerView.Adapter <AdapterFirst .ViewHolder> {
private List<Object> objectList;
private Context mContext;
AdapterSecond adapterSecond;
public AdapteFirst(List<Object> list) { objectList= list; }
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.item_list, parent, false);
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(final ViewHolder holder, int position) {
holder.itemView.setOnLongClickListener(new View.OnLongClickListener() {
#Override
public boolean onLongClick(View v) {
//query method
notifyDataSetChanged(); //working
//here it gets the nullpointerexception error
adapterSecond = new AdapteSecond();
adapterSecond.notifyDataSetChanged();
}
});
}
#Override
public int getItemCount() {
return (objectList != null? objectList.size():0);
}
public class ViewHolder extends RecyclerView.ViewHolder {
public TextView data;
public ViewHolder(View itemView) {
super(itemView);
data= (TextView) itemView.findViewById(R.id.text);
}
}
}
AdapterSecond
public class AdapterSecond extends
RecyclerView.Adapter <AdapterSecond.ViewHolder> {
private List<Object> objectList;
private Context mContext;
public AdapterSecond () {}
public AdapterSecond (List<Object> list) { objectList= list; }
#Override
public AdapterSecond.ViewHolder onCreateViewHolder(ViewGroup parent,
int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.item_list_2, parent, false);
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(final AdapterSecond.ViewHolder holder, int position) {
final Object object = objectList.get(holder.getAdapterPosition());
holder.data2.setText(object.getData());
}
#Override
public int getItemCount() {
return (objectList != null? objectList.size():0);
}
public class ViewHolder extends RecyclerView.ViewHolder {
public TextView data2;
public ViewHolder(View itemView) {
super(itemView);
data2= (TextView) itemView.findViewById(R.id.text2);
}
}
}
Seems like the order of initialization of the adapters have some issues.
Just make sure that you have initialize the secondAdapter before the firstAdapter
secondAdapter= new SecondAdapter();
firstAdapter = new FirstAdapter();
Just check the order in which they initialize!

RecyclerView in RecyclerVIew

I want to create nested RecyclerViews and the problem is that only parent is showing.
Parent Adapter
public class SectionsAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
Context mContext;
List<Section> mSections;
public SectionsAdapter(Context context, List<Section> sections) {
mContext = context;
mSections = sections;
}
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.view_section, parent, false);
return new SectionViewHolder(view);
}
#Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int pos) {
Section section = mSections.get(pos);
if (holder instanceof SectionViewHolder) {
SectionViewHolder sectionVH = (SectionViewHolder) holder;
sectionVH.mTitle.setText(section.getTitle());
LinearLayoutManager manager = new LinearLayoutManager(mContext);
sectionVH.mPreferences.setLayoutManager(manager);
PreferencesAdapter preferencesAdapter = new PreferencesAdapter(mContext, section.getPreferences());
sectionVH.mPreferences.setAdapter(preferencesAdapter);
sectionVH.mPreferences.getAdapter().notifyDataSetChanged();
}
}
#Override
public int getItemViewType(int pos) {
return 0;
}
#Override
public int getItemCount() {
return mSections.size();
}
}
Child Adapter
public class PreferencesAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
public static final int VIEW_BOOLEAN = 0;
public static final int VIEW_INT = 1;
Context mContext;
List<Preference> mPreferences;
public PreferencesAdapter(Context context, List<Preference> preferences) {
mContext = context;
mPreferences = preferences;
}
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view;
switch (viewType) {
default:
view = LayoutInflater.from(parent.getContext()).inflate(R.layout.view_preference_boolean, parent, false);
return new BooleanPreferenceViewHolder(view);
}
}
#Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int pos) {
Preference preference = mPreferences.get(pos);
if (holder instanceof BooleanPreferenceViewHolder) {
BooleanPreferenceViewHolder booleanPreferenceVH = (BooleanPreferenceViewHolder) holder;
booleanPreferenceVH.mPreferenceTitle.setText(preference.getTitle());
booleanPreferenceVH.mPreferenceExplanation.setText(preference.getExplanation());
booleanPreferenceVH.mBooleanSwitch.setChecked((Boolean) preference.getValue());
}
}
#Override
public int getItemViewType(int pos) {
return VIEW_BOOLEAN;
}
#Override
public int getItemCount() {
return mPreferences.size();
}
}
Parent View Holder
public class SectionViewHolder extends RecyclerView.ViewHolder {
public TextView mTitle;
public RecyclerView mPreferences;
public SectionViewHolder(View v) {
super(v);
mTitle = (TextView) v.findViewById(R.id.sectionTitle);
mPreferences = (RecyclerView) v.findViewById(R.id.preferences);
}
}
Child View Holder
public class BooleanPreferenceViewHolder extends RecyclerView.ViewHolder {
public TextView mPreferenceTitle;
public TextView mPreferenceExplanation;
public Switch mBooleanSwitch;
public BooleanPreferenceViewHolder(View v) {
super(v);
mPreferenceTitle = (TextView) v.findViewById(R.id.preferenceTitle);
mBooleanSwitch = (Switch) v.findViewById(R.id.booleanSwitch);
mPreferenceExplanation = (TextView) v.findViewById(R.id.preferenceExplanation);
}
}
So I noticed that is showing only parent title and its recyclerview is empty. Also child onBindViewHolder method is not calling.
You can achieve what you want with only one RecyclerView, overriding the getItemViewType method properly. You can see an example here.
Below is an example using your Section, Preference and BooleanPreferenceViewHolder classes with the library SectionedRecyclerViewAdapter.
First create a section class:
class MySection extends StatelessSection {
String title;
List<Preference> mPreferences;
public MySection(String title, List<Preference> preferences) {
// call constructor with layout resources for this Section header, footer and items
super(R.layout.section_header, R.layout.section_footer, R.layout.section_item);
this.title = title;
this.mPreferences = preferences;
}
#Override
public int getContentItemsTotal() {
return mPreferences.size(); // number of items of this section
}
#Override
public RecyclerView.ViewHolder getItemViewHolder(View view) {
// return a custom instance of ViewHolder for the items of this section
return new BooleanPreferenceViewHolder(view);
}
#Override
public void onBindItemViewHolder(RecyclerView.ViewHolder holder, int position) {
BooleanPreferenceViewHolder itemHolder = (BooleanPreferenceViewHolder) holder;
// bind your view here
itemHolder.mPreferenceExplanation.setText(mPreference.get(position).getExplanation());
}
#Override
public RecyclerView.ViewHolder getHeaderViewHolder(View view) {
return new SimpleHeaderViewHolder(view);
}
#Override
public void onBindHeaderViewHolder(RecyclerView.ViewHolder holder) {
MyHeaderViewHolder headerHolder = (MyHeaderViewHolder) holder;
// bind your header view here
headerHolder.tvItem.setText(title);
}
}
Then you set up the RecyclerView with your Sections:
// Create an instance of SectionedRecyclerViewAdapter
SectionedRecyclerViewAdapter sectionAdapter = new SectionedRecyclerViewAdapter();
MySection section1 = new MySection(mSections.get(0).getTitle(), mSections.get(0).getPreferences());
MySection section2 = new MySection(mSections.get(1).getTitle(), mSections.get(1).getPreferences());
// Add your Sections
sectionAdapter.addSection(section1);
sectionAdapter.addSection(section2);
// Set up your RecyclerView with the SectionedRecyclerViewAdapter
RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recyclerview);
recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
recyclerView.setAdapter(sectionAdapter);

Categories

Resources