5

I have a recyclerview(parent) that populated with some recyclerviews(child) in a fragment and I want to update each of the nested recyclerviews(child) directly from fragment with an action (for example click action), how can I do this in a perfect and efficient manner?

Initial ParentAdapter

     ParentAdapter adapter = new ParentAdapter(dataSet);
     mBinding.recyclerView.setAdapter(adapter);

ParentAdapter.java

public class MainAdapter extends RecyclerView.Adapter<MainAdapter.ViewHolder> {

    private final RecyclerView.RecycledViewPool viewPool;
    private List<CartItemCategory> dataSet;

    public MainAdapter(List<CartItemCategory> dataSet) {

        this.dataSet = dataSet;
        
    }

    @NonNull
    @Override
    public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        ShoppingCardParentItemLayoutBinding mBinding = ShoppingCardParentItemLayoutBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false);
        return new ViewHolder(mBinding);
    }

    @Override
    public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
        holder.mBinding.setCartItemCategory(dataSet.get(position));

        ChildAdapter childAdapter = new ChildAdapter(dataSet.get(position).getCartItems());
        holder.mBinding.recyclerView.setHasFixedSize(true);
        holder.mBinding.recyclerView.setAdapter(childAdapter);
        holder.mBinding.recyclerView.setRecycledViewPool(viewPool);
    }

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

    class ViewHolder extends RecyclerView.ViewHolder {

        ShoppingCardParentItemLayoutBinding mBinding;

        ViewHolder(@NonNull ShoppingCardParentItemLayoutBinding mBinding) {
            super(mBinding.getRoot());
            this.mBinding = mBinding;
        }
    }

}

ChildAdapter.java

public class ChildAdapter extends RecyclerView.Adapter<InnerAdapter.ViewHolder> {

    private List<CartItem> cartItems;

    public ChildAdapter(List<CartItem> cartItems) {
        this.cartItems = cartItems;
    }

    @NonNull
    @Override
    public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        ShoppingCardItemLayoutBinding mBinding = ShoppingCardItemLayoutBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false);
        return new ViewHolder(mBinding);
    }

    @Override
    public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
        holder.mBinding.setCartItem(cartItems.get(position));
    }

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

    class ViewHolder extends RecyclerView.ViewHolder {

        ShoppingCardItemLayoutBinding mBinding;

        ViewHolder(@NonNull ShoppingCardItemLayoutBinding mBinding) {
            super(mBinding.getRoot());
            this.mBinding = mBinding;
            }
    }

}

Parent recyclerview

<androidx.recyclerview.widget.RecyclerView
  android:id="@+id/recycler_view"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
>

Child item layout

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:android="http://schemas.android.com/apk/res/android"
    >

    <androidx.constraintlayout.widget.ConstraintLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content">

        <androidx.recyclerview.widget.RecyclerView
            android:id="@+id/recycler_view"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

        </androidx.constraintlayout.widget.ConstraintLayout>
</layout>
Danial Nazari
  • 111
  • 4
  • 10

1 Answers1

8

In your child adapter, you can create some insert, update, delete etc methods like this:

public class ChildAdapter extends RecyclerView.Adapter<InnerAdapter.ViewHolder> {
// ...
public void update(int position, CartItem newCartItem) {
  cartItems.set(position, newCartItem);
  notifyDataSetChanged();                    // <--- THIS IS THE MAIN THING
}

public void add(CartItem newCartItem) {
  cartItems.add(newCartItem);
  notifyDataSetChanged();                    // <--- THIS IS THE MAIN THING
}

public void delete(int position) {
  cartItems.remove(position);
}

// ...
}

After that, you can call these methods on a button click event like this:

Button btn = findViewById(R.id.btn);
btn.setOnClickListener( v -> {
  CartItem cartItem = new CartItem(); // <-- initialize properly
  childAdapter.add(newCartItem); 
// OR to update
// childAdapter.update(position,  newCartItem);  // <-- the position where you want to update 

// OR to delete
// childAdapter.delete(position); // <-- item at position that you want to delete

});

I think you can do it in this way.

how can I access to childAdapter for each child item?

I think you need these 2 things:

  1. get the viewHolder for ith position of a RecyclerView
  2. get Adapter from a recyclerView

you can access viewHolder in this way: ViewHolder vh = myRecyclerView.findViewHolderForAdapterPosition(pos); (reference)

And you can get the adapter like this way: ChildAdapter adapter = (ChildAdapter)mRecyclerView.getAdapter();

So suppose you want to get the get childAdapter from YourActivity / YourFragment. By combining those 2, you can do something like this:

//... inside your activity / fragment
 
private void myUpdate(int i, int j, CartItem cartItem) {
  // 1. get ith item of the parent recyclerView
  ViewHolder ithChildViewHolder = parentRecyclerView.
                                  findViewHolderForAdapterPosition(pos); 
  // 2. get it's recyclerview
  RecyclerView ithChildsRecyclerView = ithChildViewHolder.
                                       mBinding.
                                       recyclerView;
  // 3. get ithRecyclerView's adapter
  ChildAdapter ithChildAdapter = (ChildAdapter) ithChildsRecyclerView.getAdapter();

  // 4. now you should be able to do updates
  //    update at position j with new item
  ithChildAdapter.update( j, newCartItem); 
 
}

Please note that I wrote it without the project. So there might be some minor errors. But it should be like this. Make changes accordingly. Try this and let me know if it works or not. Good luck.

Qazi Fahim Farhan
  • 2,066
  • 1
  • 14
  • 26