Search code examples
javaandroidandroid-annotationsonitemclick

Annotations Recycler View ItemClick


I am trying to implement simple recycler view in my Activity based on the following tutorial from official AndroidAnnotations site: adapter link

However when I finish all the steps, and I try to implement @ItemClick method, it gives me the following error:

Error:(84, 36) error: incompatible types: RecyclerView cannot be converted to AdapterView

with the following code highlighted under my generated activity code:

...((AdapterView<?> ) this.miestnostiList).setOnItemClickListener(new OnItemClickListener() {...

As per guide, I have created the following base classes:

public abstract class RecyclerViewAdapterBase<T, V extends View> extends RecyclerView.Adapter<ViewWrapper<V>> {

    protected List<T> items = new ArrayList<T>();

    @Override
    public int getItemCount() {
        return items.size();
    }

    @Override
    public final ViewWrapper<V> onCreateViewHolder(ViewGroup parent, int viewType) {
        return new ViewWrapper<V>(onCreateItemView(parent, viewType));
    }

    protected abstract V onCreateItemView(ViewGroup parent, int viewType);
}


public class ViewWrapper<V extends View> extends RecyclerView.ViewHolder {

    private V view;

    public ViewWrapper(V itemView) {
        super(itemView);
        view = itemView;
    }

    public V getView() {
        return view;
    }
}

Then I created my row view item as following:

@EViewGroup(R.layout.activity_list_miestnosti_row)
public class MiestnostItemView extends LinearLayout{
    @ViewById(R.id.txt_miestnost_row_nazov)
    TextView nazov;

    public MiestnostItemView(Context context) {
        super(context);
    }

    public void bind(Miestnost miestnost){
        nazov.setText(miestnost.getNazov());
    }
}

and finally my adapter class:

public class ListMiestnostiAdapter extends RecyclerViewAdapterBase<Miestnost, MiestnostItemView> {
    @RootContext
    Context context;


    @Override
    protected MiestnostItemView onCreateItemView(ViewGroup parent, int viewType) {
        return MiestnostItemView_.build(context);
    }

    @Override
    public void onBindViewHolder(ViewWrapper<MiestnostItemView> holder, int position) {
        MiestnostItemView view = holder.getView();
        Miestnost miestnost = items.get(position);

        view.bind(miestnost);
    }
}

Under my Activity I initialize my adapter in @AfterViews section:

    @ViewById
    RecyclerView miestnostiList;

    ListMiestnostiAdapter adapter;

    @AfterViews
    void bindAdapter() {
        GetData();//fetch data

        adapter = new ListMiestnostiAdapter();
        adapter.addData(miestnosti);
        RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(getApplicationContext());
        miestnostiList.setLayoutManager(layoutManager);
        miestnostiList.setItemAnimator(new DefaultItemAnimator());
        miestnostiList.addItemDecoration(new DividerItemDecoration(this, LinearLayoutManager.VERTICAL));
        miestnostiList.setAdapter(adapter);

    }

Here is my @ItemClick method:

@ItemClick
void miestnostiListItemClicked(Miestnost miestnost){
    Log.i("", "iteClicked: ");
}

What am I missing here?


Solution

  • I think @ItemClick is not available with RecyclerView. You can proceed in two ways:

    1- Changing your RecyclerViewAdapterBase adding onClick support, then overriding that method into child adapter like so:

    public abstract class RecyclerViewAdapterBase<T, V extends View & ViewWrapper.Binder<T>> extends RecyclerView.Adapter<ViewWrapper<T, V>> {
    
        protected List<T> mItems = new ArrayList<T>();
    
        @Override
        public final ViewWrapper<T, V> onCreateViewHolder(ViewGroup parent, int viewType) {
            return new ViewWrapper<T, V>(onCreateItemView(parent, viewType));
        }
    
        protected abstract V onCreateItemView(ViewGroup parent, int viewType);
    
        @Override
        public final void onBindViewHolder(ViewWrapper<T, V> viewHolder, int position) {
            V view = viewHolder.getView();
            T data = mItems.get(position);
    
        /*************************************************************/
        *       AT THIS POINT IT TRY TO SET A CLICK LISTENER     */
        /*************************************************************/
            setOnClickListener(view, data);
    
            view.bind(data);
        }
    
        @Override
        public int getItemCount() {
            return null == mItems ? 0 : mItems.size();
        }
    
        public void add(T item) {
            mItems.add(item);
            notifyDataSetChanged();
        }
    
        public void addAll(Collection<T> collection) {
            mItems.addAll(collection);
            notifyDataSetChanged();
        }
    
        public void clear() {
            mItems.clear();
        }
    
    
        /**
         * override this into child adapter to manage click event
         */
        public void setOnClickListener(View v, T item) {}
    }
    

    This is the child adapter

    @EBean
    public class ChildAdapter extends RecyclerViewAdapterBase<Child, ChildView> {
    
    @RootContext
    Context ctx;
    @Bean(ChildFinder.class)
    IChildFinder finder;
    
    @Bean
    OttoBus mOttoBus;
    
    /**
     * get data by finder
     */
    public void initAdapter() {
        mItems = finder.findAll();
    }
    
    @Override
    public int getItemViewType(int position) {
        return position;
    }
    
    @Override
    protected ChildView onCreateItemView(ViewGroup parent, int viewType) {
        return ChildView_.build(ctx);
    }
    
    
    @Override
    public void setOnClickListener(View v, final Child item) {
        v.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mOttoBus.post(new RequestChildEvent(item));
            }
        });
    }
    }
    

    2- Otherwise if you are using custom views you can follow an event driven approach binding you click directly on the view (for example on the root view of your custom view) and then sending an event to the component that must react to the click