0

I have nested adapters for two RecyclerViews kind of like so:
Parent Adapter:

public class ParentAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
    public static ArrayList<ParentItem> parentItemList;

    private RecyclerView.RecycledViewPool viewPool = new RecyclerView.RecycledViewPool();

    private com.example.todotestapp.ChildAdapter childAdapter;

    public ParentAdapter(ArrayList<ParentItem> parentItemList) {
        this.parentItemList = parentItemList;
    }

    public class ParentViewHolder extends RecyclerView.ViewHolder {

        private RecyclerView childRecyclerView;
        public ParentViewHolder(final View parentView) {
            super(parentView);

            childRecyclerView = parentView.findViewById(R.id.child_recyclerview);
        }
    }

    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        Context context = parent.getContext();
        LayoutInflater inflater = LayoutInflater.from(context);
        View parentView = inflater.inflate(R.layout.parent_layout, parent, false);
        return new ParentViewHolder(parentView);
    }

    @Override
    public void onBindViewHolder(final RecyclerView.ViewHolder holder, final int position) {

        final ParentItem someParentItem = parentItemList.get(position);

        ArrayList<ChildItem> childItemList = someParentItem.getChildItemList();
        RecyclerView childRecyclerView = ((ParentViewHolder) holder).childRecyclerView;
        LinearLayoutManager layoutManager = new LinearLayoutManager(childRecyclerView.getContext());
        layoutManager.setInitialPrefetchItemCount(childItemList.size());
        childAdapter = new com.example.todotestapp.ChildAdapter(childItemList);
        childRecyclerView.setLayoutManager(layoutManager);
        childRecyclerView.setAdapter(childAdapter);
        childRecyclerView.setRecycledViewPool(viewPool);

    }

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

Child Adapter:

public class ChildAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
    private ArrayList<ChildItem> childItemList;

    public ChildAdapter(ArrayList<ChildItem> childItemList) {
        this.childItemList = childItemList;
    }

    public class ChildViewHolder extends RecyclerView.ViewHolder {
        CheckBox childCheckBox;

        public ChildViewHolder(final View childView) {
            super(childView);

            childCheckBox = childView.findViewById(R.id.child_checkbox);
            childCheckBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
                @Override
                public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                    ChildItem checkedChildItem = childItemList.get(getAdapterPosition());

                    ParentItem parentItemOfCheckedChildItem = checkedChildItem.getParentItem();
                    int parentAdapterPos = ParentAdapter.parentItemList.indexOf(parentItemOfCheckedChildItem);
                    int mainPos = MainActivity.mainParentItemList.indexOf(parentItemOfCheckedChildItem);
                    ArrayList<ChildItem> aChildItemList = parentItemOfCheckedChildItem.getChildItemList();
                    aChildItemList.remove(checkedChildItem);
                    childItemList.remove(checkedChildItem);
                    parentItemOfCheckedChildItem.setChildItemList(aChildItemList);
                    ParentAdapter.parentItemList.set(parentAdapterPos, parentItemOfCheckedChildItem);
                    MainActivity.mainParentItemList.set(mainPos, parentItemOfCheckedChildItem);

                    MainActivity.mainChildItemList.remove(checkedChildItem);
                    checkedChildItem.setIsChecked(true);
                    MainActivity.mainChildItemList.add(checkedChildItem);

                    ParentItem checkedParentItem = ParentAdapter.parentItemList.get(ParentAdapter.parentItemList.size() - 1);
                    checkedParentItem.addToChildItemList(checkedChildItem);
                    ParentAdapter.parentItemList.set(ParentAdapter.parentItemList.size() - 1, checkedParentItem);

                    notifyDataSetChanged();
                }
            });
        }
    }
    @NonNull
    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        Context context = parent.getContext();
        LayoutInflater inflater = LayoutInflater.from(context);
        View childView = inflater.inflate(R.layout.child_layout, parent, false);
        return new ChildViewHolder(childView);
    }
    @Override
    public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
        final ChildItem aChildItem = childItemList.get(position);
    }

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

I know the ChildAdapter is pretty messy, but I'm having trouble handling the data. I'd like to delete the checkedChildItem from its current ParentItem, add it to a new ParentItem, and then have the data refreshed. My current code does the first two steps (deletes the ChildItem from the original ParentItem's childItemList and adds it to the new ParentItem's) but only displays the data after the activity is refreshed.
I've tried passing the data to the ParentAdapter in a "updateDataAfterChecked" method, but I still can't update it since the ChildItemViewHolder is a static context and notifyDataSetChanged() is not, so I can't seem to find a way to update the ParentAdapter without going to a different activity and back again. Any suggestions?
------------------------------------EDIT----------------------------------------
I was able to access .notifyDataSetChanged() by utilizing LiveData for the ParentItemList, but the ChildItem still doesn't show up in the second ParentItem until the page is refreshed (if I call finish() then startActivity(getIntent()), everything works as it's supposed to, except this causes a jarring effect that I dislike). Any suggestions to help fix this issue? Thanks.
------------------------------------EDIT----------------------------------------
What I'm aiming for is something like what the Google Tasks app (android) does--if you check off an item, it gets removed from its date and added to "Completed" in real time; I don't know if this information helps with answers at all, but I thought it'd be worth mentioning.

2 Answers2

0

You should use Sectioned-RecyclerView instead of RecyclerView.

Refer below code: https://github.com/IntruderShanky/Sectioned-RecyclerView

Hope, above link would help you.

Daddys Code
  • 581
  • 2
  • 8
  • Not to be rude but that adapter was last updated four years ago... if you look at the source code... it's not the most efficient implementation (notifyDataSetChanged creates a new list, transforms it and then delivers the notify just to name one thing, all this happening on the MainThread). – Martin Marconcini Feb 18 '21 at 12:46
  • I agree with your comment; I'm more looking for a way to just implement something into my existing code. Having to implement a whole new library and (basically) recreate the app isn't necessarily ideal. – Nishian3695 Feb 19 '21 at 23:41
0

Figured it out using ViewModels and MutableLiveData.
In MainActivity:

public class MainActivity extends AppCompatActivity implements LifecycleOwner {
    public static ChildViewModel childViewModel;
    public static ArrayList<ChildItem> childAdapterData;
    private ParentAdapter parentAdapter;
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ...
        setViewModel();
        // Populate childAdapterData in setAdapter()
        setAdapter();
        setRecyclerView();
        updateViewModel();
    }
    ...
    public static void updateViewModel() {
        childViewModel.getChildItemLiveData().setValue(childAdapterData);
    }

    public void setViewModel() {
        childViewModel = new ViewModelProvider(this).get(ChildViewModel.class);
        final Observer<ArrayList<ChildItem>> observer = new Observer<ArrayList<ChildItem>>() {
            @Override
            public void onChanged(ArrayList<ChildItem> childItems) {
                // Do things
                // Don't have to do notifyDataSetChanged--also notifyItemRangeChanged(), etc.
                parentAdapter.notifyDataSetChanged();
            }
        };
        childViewModel.getChildItemLiveData().setValue(childAdapterData);
        childViewModel.getChildItemLiveData().observe(this, observer);
    }
}


In ChildAdapter:

public class ChildAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
    private ArrayList<ChildItem> childItemList;

    public ChildAdapter(ArrayList<ChildItem> childItemList) {
        this.childItemList = childItemList;
    }

    public class ChildViewHolder extends RecyclerView.ViewHolder {
        CheckBox childCheckBox;

        public ChildViewHolder(final View childView) {
            super(childView);

            childCheckBox = childView.findViewById(R.id.child_checkbox);
            childCheckBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
                @Override
                public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                    ChildItem checkedChildItem = childItemList.get(getAdapterPosition());
                    // Remove from ParentItem A
                    ...
                    // Add to ParentItem B
                    ...
                    MainActivity.childAdapterData.set(parentItemAPosition, parentItemA);
                    MainActivity.childAdapterData.set(parentItemBPosition, parentItemB);
                    MainActivity.updateViewModel();
                }
            });
        }
    }
...

}


Finally, the ViewModel

public class ChildViewModel extends ViewModel {
    public MutableLiveData<ArrayList<ChildItem>> childItemLiveData;

    public MutableLiveData<ArrayList<ChildItem>> getChildItemLiveData() {
        if(childItemLiveData == null) {
            childItemLiveData = new MutableLiveData<>();
        }
        return childItemLiveData;
    }
}