0

I have 2 spinners in my recycler view. Now my 2nd spinner value depends on the 1st spinner selected item.

I am able to bind data in spinner 1 but when I try to bind spinner 2 data based on setOnItemSelectedListener of spinner 1 it will only bind for a visible item on the screen.

I want to bind spinner 2 data even if it is not visible on the screen. I have the following code for the adapter :

public class CustomerAdapter extends RecyclerView.Adapter<CustomerAdapter.CardViewHolder> {

    private ArrayList<MainDetails> mMainDetails;
    private Context mContext;

    public CustomerAdapter(Context mcontext, ArrayList<MainDetails> mainDetails) {
        mContext = mcontext;
        mMainDetails = mainDetails;
    }


    private Context getContext() {
        return mContext;
    }

    @Override
    public CardViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
        Context context = viewGroup.getContext();
        View itemView = LayoutInflater.from(context).inflate(R.layout.row_bind_data, viewGroup, false);
        return new CardViewHolder(itemView);
    }


    @Override
    public void onBindViewHolder(final CardViewHolder cardViewHolder, int position) {

        final MainDetails testMainDetails = mMainDetails.get(position);

        ArrayAdapter<Products> spinnerUserAdapter = new ArrayAdapter<Products>(getContext(), R.layout.dropdown_item, testMainDetails.getUsers());
        spinnerUserAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
        cardViewHolder.spinner1.setAdapter(spinnerUserAdapter);

        cardViewHolder.spinner1.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
                try {
                    Products pp = (Products) parent.getSelectedItem();
                    ArrayAdapter<Orders> spinnerPPAdapter = new ArrayAdapter<Orders>(getContext(), R.layout.pc_estimator_dropdown_item, pp.getOrders());
                    spinnerPPAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
                    cardViewHolder.spinner2.setAdapter(spinnerPPAdapter);
                } catch (Exception e) {
                    Log.e("error", e.toString());
                }
            }

            @Override
            public void onNothingSelected(AdapterView<?> parent) {

            }
        });

        cardViewHolder.spinner2.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
               //other operation
            }

            @Override
            public void onNothingSelected(AdapterView<?> parent) {

            }
        });

    }

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


    public static class CardViewHolder extends RecyclerView.ViewHolder {

        public Spinner spinner1;
        public Spinner spinner2;

        public CardViewHolder(View v) {
            super(v);
            spinner1 = (Spinner) v.findViewById(R.id.spinner1);
            spinner2 = (Spinner) v.findViewById(R.id.spinner2);

        }
    }
}

My spinner cardViewHolder.spinner1.setOnItemSelectedListener method only calls for visible items on screens but I want to bind all data even if it not visible.

iamdhavalparmar
  • 1,090
  • 6
  • 23

2 Answers2

0

I think you need to implement everything inside ViewHolder. Let me show you an example:

 @Override
    public void onBindViewHolder(@NonNull SomeHolder holder, int position) {
        if (SomeDataList.size() > 0) {
            SomeData data = SomeDataList.get(position);
            holder.bindData(data);
        }
    }

Then in holder class:

public class SomeHolder extends RecyclerView.ViewHolder
        implements View.OnClickListener {

    private final TextView tvAddress;
    private final TextView tvAccountNumber;
    private final TextView tvName;

    private SomeData someData;

    public SomeHolder(@NonNull View itemView) {
        super(itemView);
        tvAccountNumber = itemView.findViewById(R.id.item_point_account_number);
        tvName = itemView.findViewById(R.id.item_point_subscr_name);
        tvAddress = itemView.findViewById(R.id.item_point_address);
       
        itemView.setOnClickListener(this);
    }

    public void bindData(SomeData data) {
        someData = data;
        tvAddress.setText(data.getAddress());
        //other stuff
    }

    @Override
    public void onClick(View v) {
        if (someData!=null){
           tvName.setText(someData.getName());
            //code for click event
        }
    }
}
Alex Rmcf
  • 804
  • 7
  • 14
  • Do you really know what SPINNER is? Just posting your random m file code in stack overflow. – Kishan Solanki Feb 22 '22 at 14:31
  • maybe yes or I just posting your random m file code in stack overflow – Alex Rmcf Feb 23 '22 at 13:26
  • Or I just advised to write some code another way to make it more readable. Or I needed to urgently get away from writing an answer, and then I forgot to finish it. I just do not remember – Alex Rmcf Feb 23 '22 at 13:28
0

straight inside onBindViewHolder you are setting only one adapter, for spinner1 and nothing for spinner2 - it got its adapter only after onItemSelected call of spinner1

if you want to set some initial values for spinner2 you have to initiate its adapter inside onBindViewHolder, not only in onItemSelected

move your adapter initiation code to separated method

public void setUpSpinner2(Spinner spinner, Products pp) {
    try {
        ArrayAdapter<Orders> spinnerPPAdapter = new ArrayAdapter<Orders>(getContext(), R.layout.pc_estimator_dropdown_item, pp.getOrders());
        spinnerPPAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
        spinner.setAdapter(spinnerPPAdapter);
    } catch (Exception e) {
        Log.e("error", e.toString());
    }
}

then inside onItemSelected call it

public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
    Products pp = (Products) parent.getSelectedItem();
    setUpSpinner2(cardViewHolder.spinner2, pp);
}

and also call setUpSpinner2 straight inside onBindViewHolder with null check (is item selected on start)

if (spinnerUserAdapter.getSelectedItem() != null) {
    Products pp = (Products) spinnerUserAdapter.getSelectedItem();
    setUpSpinner2(cardViewHolder.spinner2, pp);
}

btw. I see you aren't storing spinner1 selected value anywhere, so after recycling both spinners will be empty again. so inside onItemSelected get position of selected item (there is method getSelectedItemPosition) and store it in some array

//top of adapters code
private ArrayList<MainDetails> mMainDetails;
private Context mContext;
private SparseArray<Integer> selectedItemsForPositions = new SparseArray<>();

inside onItemSelected and onNothingSelected put/clear selected value with this line (don't mix positions of onBindViewHolder and onItemSelected, name them differently)

selectedItemsForPositions.put(onBindViewHolderPosition, parent.getSelectedItemPosition());
// or put null if nothing selected

when you have this array which is keeping selected positions then restore this position just after spinner1 adapter set up

cardViewHolder.spinner1.setAdapter(spinnerUserAdapter);
Integer selectedPosition = selectedItemsForPositions.get(onBindViewHolderPosition);
if(selectedPosition != null) spinnerUserAdapter.setSelection(selectedPosition);
snachmsm
  • 17,866
  • 3
  • 32
  • 74