4

I'm familiar with MVVM in WPF, but am in the process of porting an existing Android app to make use of a ViewModel class and LiveData for the first time.

The app "as/was" has a custom ArrayAdapter that is used to correctly display the items contained in a List in a gridview. The code that does that looks essentially like this ("essentially" because there are actually 4 such grids in the activity that all do it like this):

ArrayAdapter<String> playerAdapter = new MyAdapter<String>(this, R.layout.grid_item, playerList);

gridView.setAdapter(playerAdapter)

and when the playerList contents changed, there was an explicit call to

playerAdapter.notifyDataSetChanged()

Since my goal is to have the grid respond automatically when the playerList changes, and never have to notify anything, it seems now that the "playerList" needs to become a MutableLiveData<List<String>>.

I suspect I am going to have a problem though-

The MyAdapter class extends ArrayAdapter<T>

So in practice it's going to become an

ArrayAdapter<MutableLiveData<List<String>>>

But a MutableLiveData isn't going to work there, right?

I could unwrap it and make the call to create it look like this:

ArrayAdapter<String> playerAdapter = 
new MyAdapter<String>(this, R.layout.grid_item, playerList.getValue());

Is this correct? It seems the way of madness.

Ultimately my goal is to just assign the gridView's android:adapter property to this thing in xml and never have to think about it anymore (beyond the required calls to setvalue() and postValue() when I modify the underlying list...which I'm not even sure how would work here.

I would hope there's already a MutableLiveData Collection that's ready to go somewhere and I'd use that.

What the standard way to do this?

JoeHz
  • 2,136
  • 1
  • 18
  • 29

1 Answers1

4

I believe the way you are thinking is wrong. Don't worry about this:

ArrayAdapter<MutableLiveData<List<String>>>

You will get a list thats all. MutableLiveData is to set a livedata object like setValue() or postValue() manually. Just set your below code whenever liveData gets triggered and gives you the new playerList, something like this:

viewModel.getPlayListObservable().observe(this, new Observer<List<String>>() {
        @Override
        public void onChanged(List<String> playerList) {
            ArrayAdapter<String> playerAdapter = new MyAdapter<String>(this, R.layout.grid_item, playerList);
            gridView.setAdapter(playerAdapter);
            playerAdapter.notifydataChanged();
        }
    });
Prashanth Verma
  • 588
  • 3
  • 11
  • So to confirm I get this: PlayerListObservable would be the MutableLiveData of the List and I'd have a method observe changes to that which would set the contents of the GridView? So the GridView and Mutable List actually are unaware of one another? – JoeHz Nov 21 '18 at 03:55
  • I believe that the last line should be playerAdapter.notifyDataSetChanged(); no? – JoeHz Nov 21 '18 at 08:16
  • yes..i will change it. Actually we dont need that as you are setting the adapter in before line. Regarding your 1st comment, yes GridView and Mutable List are unaware of each other as they will be in different layers (if you want to follow architectural pattern). Mutable List will be in ViewModel where as GridView is in View. – Prashanth Verma Nov 21 '18 at 08:41
  • 3
    This will cost you a lot of memory - initializing a new adapter every time a new list is received. Also, you dont need to notify the adapter after changing the adapter. – Jian Astrero Oct 29 '19 at 07:26
  • I agree that was just for an example, ideally the first 2 lines of initializing and setting adapter should be outside the observable. If there is change in the list then get the appropriate list and use notifydatachanged() – Prashanth Verma Oct 29 '19 at 09:44