Android butterknife Unable to bind views into ViewHolder - android

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;

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

RecyclerView Adapter don't see ViewHolder

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

RecyclerView generic adapter with DataBinding

I have created generic adapter for RecyclerView by using DataBinding. Here is small code snippet
public class RecyclerAdapter<T, VM extends ViewDataBinding> extends RecyclerView.Adapter<RecyclerAdapter.RecyclerViewHolder> {
private final Context context;
private ArrayList<T> items;
private int layoutId;
private RecyclerCallback<VM, T> bindingInterface;
public RecyclerAdapter(Context context, ArrayList<T> items, int layoutId, RecyclerCallback<VM, T> bindingInterface) {
this.items = items;
this.context = context;
this.layoutId = layoutId;
this.bindingInterface = bindingInterface;
}
public class RecyclerViewHolder extends RecyclerView.ViewHolder {
VM binding;
public RecyclerViewHolder(View view) {
super(view);
binding = DataBindingUtil.bind(view);
}
public void bindData(T model) {
bindingInterface.bindData(binding, model);
}
}
#Override
public RecyclerViewHolder onCreateViewHolder(ViewGroup parent,
int viewType) {
View v = LayoutInflater.from(parent.getContext())
.inflate(layoutId, parent, false);
return new RecyclerViewHolder(v);
}
#Override
public void onBindViewHolder(RecyclerAdapter.RecyclerViewHolder holder, int position) {
T item = items.get(position);
holder.bindData(item);
}
#Override
public int getItemCount() {
if (items == null) {
return 0;
}
return items.size();
}
}
You can find full code in Github repo : Recyclerview-Generic-Adapter
The problem i am facing is after using generic adapter RecyclerView loading time increase and for a second it shows design time layout and than loads original data.
The piece you're missing is the binding.executePendingBindings() in bindData:
public void bindData(T model) {
bindingInterface.bindData(binding, model);
binding.executePendingBindings();
}

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, slow scrollToPosition, setSelected

Prompt, faced with scrollToPosition speed. I RecyclerView 900 positions and need to quickly establish a position as scrollToPosition very slow, c ListView such problems were not setSelection working out perfectly. It is possible to accelerate the scrollToPosition?
public class EventAdapter extends RecyclerView.Adapter<EventAdapter.Holder> {
final static public String TAG = "EventAdapter";
Context context;
List<Event> items;
public EventAdapter(List<Event> items) {
this.items = items;
}
#Override
public EventAdapter.Holder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_list_event, parent, false);
context = parent.getContext();
return new EventAdapter.Holder(v);
}
#Override
public void onBindViewHolder(EventAdapter.Holder holder, int position) {
holder.setModel(context, items.get(position), position);
}
#Override
public int getItemCount() {
return items.size();
}
public class Holder extends RecyclerView.ViewHolder {
public View block;
Holder(View view) {
super(view);
block = (View) view.findViewById(R.id.cv);
}
public void setModel(Context context, Event model, int position) {
}
}
}
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getContext());
rv.setLayoutManager(linearLayoutManager);
rv.setHasFixedSize(true);
linearLayoutManager.scrollToPosition(index);
There are couple of ways to do it:
1) Try smoothScrollToPosition as : [will certainly work]
Toast.makeText(this, "Scroll...", Toast.LENGTH_SHORT).show();
myList.smoothScrollToPosition(0);
2) Also read about scrollToPositionWithOffset as this may help too

Categories

Resources