salty_coffee
salty_coffee

Reputation: 631

How to bind live data to array adapter android

I have a simple application while I'm trying to understand android/room. I would like to have my query from room to be placed into my list view.

PersonDao.class

@Query("Select name from People limit 3")
LiveData<List<String>> getThreeNames();

AvtivityMain.class

private ArrayAdapter<String> adapter;

private PersonDatabase db;
private EditText age;
private EditText name;
Person person;
private DatabaseRepository rDb;
private PersonViewModel personViewModel;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    name = findViewById(R.id.name);
    age = findViewById(R.id.age);
    adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1);
    ListView lvPerson = findViewById(R.id.lv3Poeple);
    lvPerson.setAdapter(adapter);
    personViewModel = ViewModelProviders.of(this).get(PersonViewModel.class);

}

public void addPerson(View view){
    int sAge = Integer.parseInt(age.getText().toString());
    String sName = name.getText().toString();
    person = new Person(sName, sAge);
    personViewModel.insert(person);
    System.out.println(personViewModel.getmAllPeople());
    System.out.println(personViewModel.getm3People());
    //List<String> names = personViewModel.getm3People();
    //adapter.add(personViewModel.getm3People());
}

I have commented out the code I am having problems with. I want to be able to use my query from PersonDao and have my list view show 3 names from my Room database.

Upvotes: 0

Views: 2910

Answers (1)

Mr.Drew
Mr.Drew

Reputation: 1109

You need to do a few things, the first is make sure your adapter can take new input. I would suggest creating your own custom one. When you do create it, be sure to include a method that takes your person strings as input and notifies the adapter of the change, like so:

//you need to add an update method to your adapter, so it can change it's data as your
//viewmodel data changes, something like this:
public void setPersons(List<String> personNames) {
    //myPersons should be a variable declared within your adapter that the views load info from
    myPersons = personNames;
    notifyDataSetChanged();
}

Then in your activity you should set the Adapter as a global variable so it can be accessed by multiple methods, such as your view model observer method and it's initial setup in onCreate().

//need to set up adapter variable to access in other methods to keep view model observer
//off the main thread
private ArrayAdapter myAdapter;

After that you can set up the following observer method for your ViewModel (assuming you created the ViewModel Class properly with a return method called getThreeNames() and that isn't just within your DAO as you showed above.

//set up the view model observer to be off the main thread so it isn't tied to your main
//activity lifecyle (which is the whole point/beauty of the ViewModel), you can call this
//method in your onCreate() method and should stay until onDestroy() is called
private void setupPersonViewModel() {
    PersonViewModel viewModel
            = ViewModelProviders.of(this).get(PersonViewModel.class);
    viewModel.getThreeNames().observe(this, new Observer<List<String>>() {
        @Override
        public void onChanged(@Nullable List<String> persons) {
            //so you can see when your app does this in your log
            Log.d(TAG, "Updating list of persons from LiveData in ViewModel");
            mAdapter.setPersons(persons);
        }
    });
}

Hope that answers your question. Let me know if you need any further clarification.

Upvotes: 3

Related Questions