androidmvvmadapterviewmodelandroid-fragmentactivity

Activity/Fragment and ViewModel in Adapter good practice?


Let's assume that we have Activity/Fragment which contains a RecyclerView. Furthermore, it sets an Adapter. For the sake of the example, let's say the Adapter has to have access to Fragment in order to call a method which displays a Snackbar. Moreover, Let's say there are a couple of items in the adapter. I want to delete one and remove it from the database. Therefore I should call ViewModel's methods. I've made a research but I couldn't find any information if referencing a fragment into the Adapter is good or not.

Could you help me and explain? Also for the ViewModel I've found some ideas here.

But what are the best practices?


Solution

    1. good Adapter Classes should be STATIC helping developers to keep it separated from Activity/Fragment part
    2. don't save Activity/Fragment reference inside Adapters
    3. ViewModels should belongs to Activities or Fragments
    4. Adapters should execute Activity/Fragment's actions via Callbacks/Listeners or LiveData

    Pseudo-code:

    public class MainActivity extends Activity {
        
        private interface Listener {
            void OnRemoved(@NonNull xxx removedItem);
        }
        
        private static final class MyAdapter extends ArrayAdapter<xxx> {
            private final Listener mListener;
            private MyAdapter(@NonNull final Listener listener) {
                super(...);
                this.mListener = listener;
            }
            @Override
            public void remove(xxx item) {
                super.remove(xxx); //<-- this removes item from Adapter
                this.mListener.OnRemoved(item); //<-- this triggers Activity's code
            }
        }
        
        public void onCreate(...) {
            ...
            new MyAdapter(new Listener() {
                @Override
                public void OnRemoved(@NonNull final xxx removedItem) {
                    Snakbar.makeText(....).show();
                }
            });
        }
    }