Android BottomSheetDialogFragment data changes the data in parent Fragment

Issue

Problem Statement
I have a problem of data being changed in fragment whenever the data is modified in the BottomSheetDialogFragment

App Description
In my app I have the MainActivity which host 2 Fragment in it’s ViewPager. 1st Fragment for app content and 2nd Fragment (let’s call it GalleryFragment) that shows the gallery view. User can tap on gallery item which loads up the BottomSheet (let’s call it GalleryBottomSheet) – that hosts RecyclerView to show gallery item in full screen. Now initially app feeds the GalleryFragment with the ArrayList to show the gallery items. When user clicks on the Gallery item, this ArrayList is passed to the GalleryBottomSheet.

So What’s Happening
What’s happening is whenever I am removing an item from the ArrayList in my GalleryBottomSheet, It automatically also remove that item in the ArrayList of GalleryFragment. In short, Any update in the Arraylist from GalleryBottomSheet impacting the ArrayList in GalleryFragment

What do you want
I want seperation of concerns. I don’t want the change made in the ArrayList of GalleryBottomSheet to impact the original ArrayList of GalleryFragment

Show me the damn
To make this question concise, I am adding only the important part of the code.

~ GalleryFragment.java


    public class GalleryFragment extends Fragment {

        private RecyclerView recyclerView;
        private ArrayList<String> arrayList = new ArrayList<>(); //This is the one which will be passed to the GalleryBottomSheet
        private GalleryAdapter galleryAdapter;

        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
                                 Bundle savedInstanceState) {
            View view = inflater.inflate(R.layout.fragment_gallery, container, false);

            //setting up all the UI work...

            arrayList = FindFiles(); //FindFiles is a private function searching for all file in the dir and adding the path as a string to the arraylist
            galleryAdapter = new GalleryAdapter(getActivity()); //init the adapter
            recyclerView.setAdapter(galleryAdapter); //setting the adapter

            return view;
        }
    }

    private class GalleryAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {

        private final Activity activity;


        GalleryAdapter(Activity context) {
            this.activity = context;
        }

        @NonNull
        @Override
        public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {

            View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.gallery_content_item, parent, false);
            return new ItemViewHolder(view);
            

        }

        @Override
        public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
            if(holder instanceof ItemViewHolder){
               //setting up stuff..
            }
        }

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



        private class ItemViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
            ImageView imageView;
            ItemViewHolder(View itemView) {
                super(itemView);
                imageView = itemView.findViewById(R.id.imageView);
                itemView.setOnClickListener(this);
            }

            @Override
            public void onClick(View view) {
                

                Bundle bundle = new Bundle();
                bundle.putStringArrayList("list", arrayList);

                GalleryBottomSheet galleryBottomSheet= GalleryBottomSheet.newInstance();
                galleryBottomSheet.setOnRefreshListener( new GalleryBottomSheet.GalleryInterface() {
                    @Override
                    public void onRefresh() {
                        //here the actual arrayList size reduced even though the arrayList that was modified exist in GalleryBottomSheet
                        System.out.println("CURRENT LIST SIZE: " + arrayList.size());
                    }
                });
                galleryBottomSheet.setArguments(bundle);
                galleryBottomSheet.show(getParentFragmentManager(), "galleryPager");

                
            }



    }


~ GalleryBottomSheet.java

public class GalleryBottomSheet extends BottomSheetDialogFragment {

    static GalleryBottomSheet newInstance() {
        return new GalleryBottomSheet();
    }

    public interface GalleryInterface {
        void onRefresh();
    }

    private RecyclerView recyclerView;
    private ViewAdapter viewAdapter;
    private Button deleteBtn;
    private GalleryInterface galleryInterface;

    public void setOnRefreshListener( GalleryInterface galleryInterface){
        this.galleryInterface = galleryInterface;
    }

    @NonNull
    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        //.. setting up sheetDialog
        return bottomSheetDialog;
    }

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setStyle(BottomSheetDialogFragment.STYLE_NO_FRAME, R.style.GalleryBottomStyle);
    }

   @Override
    public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.gallery_sheet, container, false);

        Bundle bundle = getArguments();
        ArrayList<String> filePathArr = bundle.getStringArrayList("list"); //here arrayList from GalleryFragment
        
        //Setting up all UI views...

        deleteBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                int positionPager = recyclerView.computeVerticalScrollOffset(); //just for demo, in the actual app we are using addOnScrollListener for position
                filePathArr.remove(positionPager);
                viewAdapter.notifyItemRemoved(positionPager);
                galleryInterface.onRefresh(); //this is where GalleryFragment shows that the arraylist is modified too.
                Toast.makeText(getActivity(), "Deleted Successfully",Toast.LENGTH_SHORT).show();
            }
        });
        
        return view;
    }


    //setting up viewAdapter and other stuff


}

Solution

Well, it turns out the main problem is that object is stored in memory by reference. By modifying the arrayList from GalleryBottomSheet it also changes the original arrayList since the exact arrayList was referred in GalleryBottomSheet from GalleryFragment. The solution is to simply initializing a new ArrayList in GalleryBottomSheet

Changing from:

ArrayList<String> filePathArr = bundle.getStringArrayList("list");

to:

ArrayList<String> filePathArr = new ArrayList<>(bundle.getStringArrayList("list"));

Answered By – Abhinandan Chakraborty

This Answer collected from stackoverflow, is licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply

(*) Required, Your email will not be published