RecyclerView Adapter don't see ViewHolder - android

I'm trying to develop a project in accordance with MVP standarts. In the guide i followed, author created separate ViewHolder class. I tried to do the same, but Adapter refuses to work with separate ViewHolder.
There is 2 errors
Cannot resolve symbol 'LessonCardView'
'onCreateViewHolder(ViewGroup, int)' in RVAdapter clashes with 'onCreateViewHolder(ViewGroup, int)' in 'android.support.v7.widget.RecyclerView.Adapter'; attempting to use incompatible return type
RVAdapter.java
public class RVAdapter extends RecyclerView.Adapter<RVAdapter.LessonCardViewHolder> {
private String[] mDataset;
public RVAdapter(String[] dataset) {
mDataset = dataset;
}
#Override
public LessonCardViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
return new LessonCardViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.lessons_item_card, parent, false));
}
#Override
public void onBindViewHolder(LessonCardViewHolder holder, int position) {
}
#Override
public int getItemCount() {
return mDataset.length;
}
}
LessonCardViewHolcer.java
public class LessonCardViewHolder extends RecyclerView.ViewHolder implements LessonCardView {
private final TextView lessonCardText;
public LessonCardViewHolder(View itemView) {
super(itemView);
lessonCardText = (TextView) itemView.findViewById(R.id.lesson_card_view);
}
#Override
public void setLessonCardText(String text) {
lessonCardText.setText(text);
}
}
I created subclass ViewHolder that inherited from LessonCardView in RVAdapter. Errors disappeared. But i'm not sure if this the right way. If it works for someone else, then i'm doing something wrong.

Change your adapter declaration from this
public class RVAdapter extends RecyclerView.Adapter<RVAdapter.LessonCardViewHolder> {
to this
// import here your view holder
public class RVAdapter extends RecyclerView.Adapter<LessonCardViewHolder> {

It looks like from how you're providing the snippets that these classes are in different files, or not correctly nested within the same file.
Have you tried using RecyclerView.Adapter<LessonCardViewHolder> rather than RecyclerView.Adapter<RVAdapter.LessonCardViewHolder>?

LessonCardViewHolder should be a nested class in RVAdapter

Here is the complete solution - Recyclerview Adapter class example
public class IAdapter extends RecyclerView.Adapter<IAdapter.ViewHolder> {
Context context;
ArrayList<Model> modelList;
public ImagesAdapter(Context context,ArrayList<Model> modelList) {
this.context=context;
this.modelList=modelList;
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.layout_items, parent, false);
return new ViewHolderImages(view);
}
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
Model model=photo.get(position);
userViewHolder.textView.setText(model.getTitle());
}
public class ViewHolder extends RecyclerView.ViewHolder{
TextView textView;
public ViewHolderImages(View itemView) {
super(itemView);
textView=(TextView)itemView.findViewById(R.id.textView);
}
}
#Override
public int getItemCount() {
return modelList.size();
}
}

Related

Merging two mostly similar adapters for recyclerview

I have two adapters that adapt to a recycler view depending on different conditions. I want to merge them.
The issue is that I created first in the same file as the activity where it is being used and the other is in a new file.
Take it as follows:
DefaultAdapter is in the file where it is being used.
AutoCompleteAdapter is also used in the same file but is declared in other file.
I want to get rid of Default Adapter and get its funtions into AutoCompleteAdapter.
There are some issues to it: I can no more use the ParentFiles' variables.
Below is the adapter that I want to get rid of.
public class DefaultAdapter extends RecyclerView.Adapter<DefaultAdapter.ViewHolder> {
private Context context;
private AdapterView.OnItemClickListener onItemClickListener;
List<String> searchList;
#NonNull #Override
public DefaultAdapter.ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = (View) LayoutInflater.from(parent.getContext())
.inflate(android.R.layout.simple_list_item_1, null);
ViewHolder holder = new ViewHolder(view);
return holder;
}
#Override public void onBindViewHolder(#NonNull ViewHolder holder, int position) {
holder.txt.setText(
Html.fromHtml(getItem(position)).toString());///need to get rid of this error
}
#Override public int getItemCount() {
return searchList.size();
}
#NonNull public String getItem(int position) {
return searchList.get(position);
}
public class ViewHolder extends RecyclerView.ViewHolder {
TextView txt;
public ViewHolder(#NonNull View itemView) {
super(itemView);
txt = itemView.findViewById(android.R.id.text1);
itemView.setOnClickListener(new View.OnClickListener() {
#Override public void onClick(View v) {
String title = txt.getText().toString();
searchPresenter.saveSearch(title);
}
});
itemView.setOnLongClickListener(new View.OnLongClickListener() {
#Override public boolean onLongClick(View v) {
String searched = txt.getText().toString();
deleteSpecificSearchDialog(searched);
return true;
}
});
}
}
}
Please take note of the SearchPresenter. This is a variable in the parent file, that is causing major issues. Autocomplete adapter doesn't have to use it, but default have to.
This is the adapter I want it to merge into
public class AutoCompleteAdapter extends RecyclerView.Adapter<AutoCompleteAdapter.ViewHolder>
implements Filterable {
#Inject JNIKiwix currentJNIReader;
#Inject SharedPreferenceUtil sharedPreferenceUtil;
#Inject ZimReaderContainer zimReaderContainer;
private List<String> data;
private KiwixFilter kiwifilter;
private Context context;
public AutoCompleteAdapter(Context context) {
this.context = context;
data = new ArrayList<>();
kiwifilter = new KiwixFilter();
setupDagger();
}
private void setupDagger() {
CoreApp.getCoreComponent().inject(this);
}
#NonNull #Override public ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = (View) LayoutInflater.from(parent.getContext())
.inflate(android.R.layout.simple_list_item_1, null);
ViewHolder holder = new ViewHolder(view);
return holder;
}
#Override public void onBindViewHolder(#NonNull ViewHolder holder, int position) {
holder.title.setText(Html.fromHtml(getItem(position)).toString());
}
#Override
public String getItem(int index) {
String a = data.get(index);
if (a.endsWith(".html")) {
String trim = a.substring(2);
trim = trim.substring(0, trim.length() - 5);
return trim.replace("_", " ");
} else {
return a;
}
}
#Override public int getItemCount() {
return data.size();
}
public class ViewHolder extends RecyclerView.ViewHolder {
TextView title;
public ViewHolder(#NonNull View itemView) {
super(itemView);
title = itemView.findViewById(android.R.id.text1);
}
}
}
...
Note the similarity between the two, they are almost similar, autocompleteadapter is like superset of defaultadapter.
I just want to get rid of the default adapter.
Note: I have chopped off some other things from autocompeleteadapter, I think they are not required for the problem.
Noob here...
Thanks

What is the practical way write recyclerview

I saw many methods to write Recyclerview. But I do not know what is the best practice way in terms of performance.
I have two methods to write a Recyclerview, are they the same or is there in difference?
First method is to write it in separate Adapter class
Adapter.java
public class Adapter extends RecyclerView.Adapter<Adapter.MyViewHolder> {
#NonNull
#Override
public MyViewHolder onCreateViewHolder(#NonNull ViewGroup viewGroup, int i) {
return null;
}
#Override
public void onBindViewHolder(#NonNull MyViewHolder myViewHolder, int i) {
}
#Override
public int getItemCount() {
return 0;
}
class MyViewHolder extends RecyclerView.ViewHolder{
public MyViewHolder(#NonNull View itemView) {
super(itemView);
}
}
}
Second method is to write it like this inside the MainActivity or Fragment
recyclerView.setAdapter(new RecyclerView.Adapter() {
#NonNull
#Override
public RecyclerView.ViewHolder onCreateViewHolder(#NonNull ViewGroup viewGroup, int i) {
return null;
}
#Override
public void onBindViewHolder(#NonNull RecyclerView.ViewHolder viewHolder, int i) {
}
#Override
public int getItemCount() {
return 0;
}
});
}
public class MyViewHolder extends RecyclerView.ViewHolder{
public MyViewHolder(#NonNull View itemView) {
super(itemView);
}
}
The adapter should be implemented as a separated class, because it makes re-using it easier:
public class YourAdapter extends RecyclerView.Adapter<Adapter.MyViewHolder> {
private ArrayList<YourModel> list = new ArrayList();
public YourAdapter(ArrayList<YourModel> list){
this.list = list;
}
#NonNull
#Override
public MyViewHolder onCreateViewHolder(#NonNull ViewGroup viewGroup, int i) {
//return the viewholder
}
#Override
public void onBindViewHolder(#NonNull MyViewHolder myViewHolder, int i) {
//deal with data
}
#Override
public int getItemCount() {
//return the list number
}
class MyViewHolder extends RecyclerView.ViewHolder{
public MyViewHolder(#NonNull View itemView) {
super(itemView);
//bind the views
}
}
}
Than in your Activity/Fragment you can use it like this :
//after you have initialized recyclerview and added the layoutmanager
//prepare the list for the adapter
recyclerView.setAdapter(new YourAdapter(yourList));
This way you can reuse it in more than one Activity/Fragment. This pattern of reusable code should be preferred because you don't have to create the classes multiple times as anonymous classes - if needed.
the best way is to set adapter class outside main class as your explain just use your first class

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.

Android butterknife Unable to bind views into ViewHolder

in recyclerview adapter i have some view in layout and i want to bind that with butterknife library, but i get
java.lang.RuntimeException:
Unable to bind views for ir.pishguy.signalpresentationproject.Adapters.ViewHolders.
StoreListsViewHolder
at butterknife.ButterKnife.bind
error when i run application
My adapter:
public class StoreListsAdapter extends RecyclerView.Adapter<StoreListsViewHolder> {
OnCardClickListner onCardClickListner;
List<StoreLists> list = Collections.emptyList();
Context context;
public StoreListsAdapter(List<StoreLists> list, Context context) {
this.list = list;
this.context = context;
}
#Override
public StoreListsViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.store_item_fields, parent, false);
StoreListsViewHolder holder = new StoreListsViewHolder(v);
return holder;
}
#Override
public void onBindViewHolder(StoreListsViewHolder holder, final int position) {
holder.store_title.setText(list.get(position).getStoreTitle());
}
#Override
public int getItemCount() {
return list.size();
}
#Override
public void onAttachedToRecyclerView(RecyclerView recyclerView) {
super.onAttachedToRecyclerView(recyclerView);
}
}
and My ViewHolder class:
public class StoreListsViewHolder extends RecyclerView.ViewHolder {
#Bind(R.id.store_lists_root)
public LinearLayout store_lists_root;
#Bind(R.id.store_count_vitrin)
public TextView store_title;
public StoreListsViewHolder(View view) {
super(view);
ButterKnife.bind(this, view);
}
}
Check all of R.id.XXX if one of them miss or not in your layout (store_item_fields.xml) it through exception. your ViewHolder class is seems okay.
Also for finding your problem faster I recommend to empty your viewHolder ( it's shouldn't through any exception) and then add your fields one by one.
Also try to use new version of ButterKnife 8.0.1;

RecyclerView.Adapter does not see overridden onBindViewHolder method?

I use DataBindings and RecyclerView in my project.
I have a base adapter for RecyclerView. It looks like this
public abstract class BaseAdapter<T extends ViewDataBinding> extends RecyclerView.Adapter<BaseAdapter.ViewHolder> {
public BaseAdapter() {}
public class ViewHolder extends RecyclerView.ViewHolder {
public T binding;
public ViewHolder(View view) {
super(view);
binding = DataBindingUtil.bind(view);
}
}
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
... code ...
}
}
ViewHolder extended classes differs only binding field type.
After the implementation of the extended BaseAdapter class:
public class BaseAdapterExtended extends BaseAdapter<BaseAdapterExtendedBinding> {
public BaseAdapterExtended(ArrayList<ItemModel> itemModels) {
super();
mData = itemModels;
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
LayoutInflater inflater = LayoutInflater.from(parent.getContext());
return new ViewHolder(BaseAdapterExtendedBinding.inflate(inflater, parent, false).getRoot());
}
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
super.onBindViewHolder(holder, position);
}
#Override
protected View getItemRootView(ViewHolder holder) {
return holder.binding.item;
}
#Override
public int getItemCount() {
return mData.size();
}
}
i am got next compilation error:
error: BaseAdapterExtended is not abstract and does not override abstract method onBindViewHolder(BaseAdapter.ViewHolder,int) in Adapter
Seems like BaseAdapterExtended hasn't this method, but he exists.
If I change
public void onBindViewHolder(ViewHolder holder, int position)
to
public void onBindViewHolder(BaseAdapter.ViewHolder holder, int position)
Projections compiled fine, but type binding will be ViewDataBinding instead BaseAdapterExtendedBinding. Why is this happening? Any ideas?
In my case I had forgotten to parameterize my superclass. When creating the class I hadn't yet created the ViewHolder, and it was very permissive except for the error on that method. I.e.:
public class FooAdapter extends RecyclerView.Adapter {
Had to be changed to
public class FooAdapter extends RecyclerView.Adapter<FooAdapter.FooViewHolder> {
This needed to be done anyways, but the only compiler error I got was in onBindViewHolder.
in this line:
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
super.onBindViewHolder(holder, position);
}
replace ViewHolder with BaseAdapterExtended.ViewHolder
I just found out the reason to this weird issue. This is happening in my project too but only for adapters that are parametrized, like yours is. All other adapters saw the BindViewHolder() method without needing to explicitly specify the ViewHolder in the class. The solution is to parametrize the ViewHolder class with any random param type, this looks like it's a bug.
public abstract class BaseAdapter<T extends ViewDataBinding> extends RecyclerView.Adapter<BaseAdapter.ViewHolder> {
public BaseAdapter() {}
public class ViewHolder<RandomTypeNotUsed> extends RecyclerView.ViewHolder {
public T binding;
public ViewHolder(View view) {
super(view);
binding = DataBindingUtil.bind(view);
}
}
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
... code ...
}
}
Works fine for me!
//like is my imageview
#Override
public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, final int i) {
MyViewHolder myViewHolder1 = (MyViewHolder)viewHolder;
myViewHolder1.like.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(context, "yay" + i, Toast.LENGTH_SHORT ).show();
}
});
}

Categories

Resources