4

I need to get the viewholder for a specific position, but I get this error:

java.lang.NullPointerException: Attempt to read from field 'android.view.View android.support.v7.widget.RecyclerView$ViewHolder.itemView' on a null object reference

Here is my adaptor:

public class ConciergeAdapter extends RecyclerView.Adapter<ConciergeAdapter.MyViewHolder> {

    private Context context;
    private ArrayList<String> items;

    public class MyViewHolder extends RecyclerView.ViewHolder
    {
        public TextView text;
        public RelativeLayout maincon;

        public MyViewHolder(View view) {
            super(view);
            this.text = (TextView) view.findViewById(R.id.text);
            this.maincon = (RelativeLayout) view.findViewById(R.id.maincon);
        }
    }

    public ConciergeAdapter(Context context, ArrayList<String> items)
    {
        this.context = context;
        this.items = items;
    }

    @Override
    public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType)
    {
        View itemView = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.fragment_concierge_top_items, parent, false);

        return new MyViewHolder(itemView);
    }


    @Override
    public void onBindViewHolder(ConciergeAdapter.MyViewHolder holder, int position)
    {
        Random rnd = new Random();
        int color = Color.argb(255, rnd.nextInt(256), rnd.nextInt(256), rnd.nextInt(256));
        holder.maincon.setBackgroundColor(color);
    }

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

And this is the code where I am calling the adaptor and trying to get the ViewHolder:

final LinearLayoutManager layoutManager= new LinearLayoutManager(getActivity(),LinearLayoutManager.HORIZONTAL, false);
        mRecyclerView = (RecyclerView) view.findViewById(R.id.recycler_view);
        mRecyclerView.setLayoutManager(layoutManager);

        ArrayList<String> itemslist = new ArrayList<String>();
        itemslist.add("1");
        itemslist.add("1");
        itemslist.add("1");
        itemslist.add("1");
        itemslist.add("1");
        itemslist.add("1");
        itemslist.add("1");
        itemslist.add("1");
        itemslist.add("1");
        itemslist.add("1");
        itemslist.add("1");

        ConciergeAdapter adapter = new ConciergeAdapter(getActivity(),itemslist);
        mRecyclerView.setAdapter(adapter);

        //RecyclerView.ViewHolder viewholder =  mRecyclerView.findViewHolderForAdapterPosition(1); 

        View holder = layoutManager.getChildAt(0);

        RelativeLayout middle = (RelativeLayout) holder.findViewById(R.id.maincon);
        middle.getLayoutParams().height = 200;
Ole V.V.
  • 81,772
  • 15
  • 137
  • 161
stavros.3p
  • 2,244
  • 6
  • 20
  • 37
  • 1
    duplicate of http://stackoverflow.com/questions/32836844/android-recyclerview-findviewholderforadapterposition-returns-null – Stephen Mar 20 '17 at 14:50
  • It's not the same question. His problem is the swapAdapter – stavros.3p Mar 20 '17 at 14:58
  • 1
    @student He uses swapAdapter, you use setAdapter, but the underlaying workings are effectively the same, and you have not notified that your dataset had changed. I think you will find that if you look closer at that question, it will solve your problem. – Stephen Mar 20 '17 at 15:03
  • @student did you solve it? – user25 Mar 17 '19 at 22:27

2 Answers2

0

That happens because the RecyclerView has not been populated yet. I suggest you to do the intended layout operations inside onBindViewHolder of your adapter :

 @Override
public void onBindViewHolder(ConciergeAdapter.MyViewHolder holder, int position) {
    if (position == 0) { 
        RelativeLayout middle = (RelativeLayout) holder.container(R.id.maincon);
        middle.getLayoutParams().height = 200;
    }

    Random rnd = new Random();
    int color = Color.argb(255, rnd.nextInt(256), rnd.nextInt(256), rnd.nextInt(256));
    holder.maincon.setBackgroundColor(color);
}

Your MyViewHolder :

public class MyViewHolder extends RecyclerView.ViewHolder {
    public View container;
    public TextView text;
    public RelativeLayout maincon;

    public MyViewHolder(View view) {
        super(view);
        container = view;
        this.text = (TextView) view.findViewById(R.id.text);
        this.maincon = (RelativeLayout) view.findViewById(R.id.maincon);
    }
}
Nika Kurdadze
  • 2,502
  • 4
  • 18
  • 28
  • 1
    Hey thanks for the answer. This works only for one position and I don't want to restrict only to one. I want to be able to pick any viewholder from outside the adapter. – stavros.3p Mar 20 '17 at 15:29
-3

My idea is to store ViewHolders in an array as they appear in adapter.

Try to extend RecyclerView.Adapter like this:

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

 ...
 // array of ViewHolders at specific positions
 private ViewHolder[] viewHolders;

 // constructor
 public MyRecyclerViewAdapter(List items) {
     ...
     viewHolders = new ViewHolder[items.size()];
     ...
 }

 @Override
 public void onBindViewHolder(final ViewHolder holder, int position) {
     ...
     viewHolders[position] = holder;
     ...
 }

 // call this function from outside of the adapter
 public ViewHolder getViewHolder(int position) {
    return viewHolders[position];
 }
}
Marek J.
  • 310
  • 2
  • 18