5

I have a RecyclerView and I'd like to pass data to the RecyclerView.Adapter's ViewHolder's constructor in onCreateViewHolder(ViewGroup parent, int viewType).

What I'd like to do is pass a parameter (the data item itself) to the ViewHolder's constructor so that I don't have to retrieve it every time the item is clicked.

However when I try to retrieve a position in onCreateViewHolder(ViewGroup parent, int ViewType), I do not get the absolute position of the row, viewType which always returns 0.

I do not want to use RecyclerView.onItemTouchListener().

I understand now that I can use

    @Override
    public int getItemViewType(int position) {
        return super.getItemViewType(position);
    }

which can return unique positions for every item in the list. But I'd then have to write (lengthy) switch ladders to handle every item in the data structure which is tedious.

Can I use onCreateViewHolder(...) in a way that the integer parameter returns absolute positions (so that I could use the position to pass data to ViewHolder's constructor) without having to handle each item individually in a switch block ?

Here is my adapter:

public class Adapter extends RecyclerView.Adapter<Adapter.DataViewHolder> {

    ArrayList<String> mContinentList;
    ClickListener mListener;

    public interface ClickListener{

        void onContinentClicked(String continent);
    }

    public class DataViewHolder extends RecyclerView.ViewHolder{

        TextView mDataItemTextView;
        String mContinent;

        public DataViewHolder(View itemView,String continent) {
            super(itemView);

            mDataItemTextView = (TextView) itemView.findViewById(R.id.data_text_view);
            mContinent = continent;
            Log.v("continent",mContinent);
            mDataItemTextView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    mListener.onContinentClicked(mContinent);
                }
            });

        }
    }

    public Adapter(Context context, ArrayList<String> continentList){

      this.mContinentList = continentList;
      this.mListener = (ClickListener) context;
    }

    @Override
    public DataViewHolder onCreateViewHolder(ViewGroup parent, int position) {

        Log.v("position", Integer.toString(position));
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.data_item_view, parent, false);
        return new DataViewHolder(view,mContinentList.get(position));
    }

    @Override
    public void onBindViewHolder(DataViewHolder holder, int position) {

        holder.mDataItemTextView.setText(mContinentList.get(position));
    }

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

and here is my Activity:

    public class MainActivity extends AppCompatActivity implements Adapter.ClickListener{


    RecyclerView mRecyclerView;
    Adapter mAdapter;
    ArrayList<String> mDataList;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        initData();

        mRecyclerView = (RecyclerView)findViewById(R.id.recycler_view);
        mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
        mAdapter = new Adapter(this,mDataList);
        mRecyclerView.setAdapter(mAdapter);
    }

    private void initData(){

        mDataList = new ArrayList<>();
        mDataList.add("Africa");
        mDataList.add("Antartica");
        mDataList.add("Asia");
        mDataList.add("Australia");
        mDataList.add("Europe");
        mDataList.add("North America");
        mDataList.add("South America");
    }

    @Override
    public void onContinentClicked(String continent) {
        Log.v("continent",continent);
    }
}

And here are my logs:

07-14 15:53:59.271 2987-2987/com.android.test V/position: 0
07-14 15:53:59.309 2987-2987/com.android.test V/continent: Africa
07-14 15:53:59.312 2987-2987/com.android.test V/position: 0
07-14 15:53:59.312 2987-2987/com.android.test V/continent: Africa
07-14 15:53:59.315 2987-2987/com.android.test V/position: 0
07-14 15:53:59.316 2987-2987/com.android.test V/continent: Africa
07-14 15:53:59.316 2987-2987/com.android.test V/position: 0
07-14 15:53:59.316 2987-2987/com.android.test V/continent: Africa
07-14 15:53:59.316 2987-2987/com.android.test V/position: 0
07-14 15:53:59.316 2987-2987/com.android.test V/continent: Africa
07-14 15:53:59.317 2987-2987/com.android.test V/position: 0
07-14 15:53:59.317 2987-2987/com.android.test V/continent: Africa
07-14 15:53:59.317 2987-2987/com.android.test V/position: 0
07-14 15:53:59.317 2987-2987/com.android.test V/continent: Africa
user1841702
  • 2,683
  • 6
  • 35
  • 53

1 Answers1

0

You don't have to write lengthy switch block unless you want a different view for each item. getItemViewType is passed an absolute position just like onBindViewHolder, so just return the position you got from getItemViewHolder and use it directly in onCreateViewHolder i.e viewType will contain real position.

By the way sorry for the answer structure, am answering from a phone browser ;)

Indrajeet
  • 5,490
  • 2
  • 28
  • 43
Maker Jr
  • 13
  • 3
  • Thanks for this, what if I need to add a header and footer around my list and a ViewHolder each for the header, footer and data item? – user1841702 Jul 14 '16 at 11:11
  • In that case you can use a switch in the onCreateViewHolder to check if the position is 0 or yourData.size() -1. Then inflate a header base on the case. This means your first and last item will represent the header and footer respectively – Maker Jr Jul 14 '16 at 12:34