Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android implement search with view model and live data

I'm working on a project in android for a udacity course I'm currently trying to implement a search function while adhering to android architecture components and using firestore and room I'm fairly new to all these concepts so please point out anything that seems wrong.

So I made a database repository to keep my firestore and room databases in sync and to deliver the data. I'm then using viewmodel and the observer pattern (I think) so my observer gets the data and looks for changes gives it to my adapter (refreshMyList(List)) which populates a recyclerview like this :

 contactViewModel = ViewModelProviders.of(this).get(ContactsViewModel.class);
 contactViewModel.getAllContacts().observe(this, new 
 Observer<List<DatabaseContacts>>() {
        @Override
        public void onChanged(@Nullable List<DatabaseContacts> 
        databaseContacts) {
            ArrayList<DatabaseContacts> tempList = new ArrayList<>();
            tempList.addAll(databaseContacts);
            contactsAdapter.refreshMyList(tempList);
            if (tempList.size() < 1) {
                results.setVisibility(View.VISIBLE);
            } else {
                results.setVisibility(View.GONE);
            }
        }
    });

I now want to perform a search of the data, I have my room queries all set up fine and I have methods in my data repository to get contacts based on a search string but I cant seem to refresh my list I've read that there are ways to do it like Transformations.switchMap ? but i cant seem to wrap my head around how it works can anyone help me

Currently I'm trying to return a List of results from an async task, it used to return live data but I changed it as getValue() was always null, not sure if that's correct, heres the async :

private static class searchContactByName extends AsyncTask<String, Void, 
ArrayList<DatabaseContacts>> {

    private LiveDatabaseContactsDao mDao;

    searchContactByName(LiveDatabaseContactsDao dao){
        this.mDao = dao;
    }

    @Override
    protected ArrayList<DatabaseContacts> doInBackground(String... params) {
        ArrayList<DatabaseContacts> contactsArrayList = new ArrayList<>();
        mDao.findByName("%" + params[0] + "%");
        return contactsArrayList;
    }
}

I call this from my contacts repository in its own sort of wrapper :

public List<DatabaseContacts> getContactByName(String name) throws 
ExecutionException, InterruptedException {
    //return databaseContactsDao.findByName(name);
    return new searchContactByName(databaseContactsDao).execute(name).get();
}

and this is called from my view model like this :

public List<DatabaseContacts> getContactByName(String name) throws 
ExecutionException, InterruptedException {
    return  contactRepository.getContactByName(name);
}

I'm then calling this from my fragment :

private void searchDatabase(String searchString) throws ExecutionException, 
InterruptedException {
    List<DatabaseContacts> searchedContacts = 
    contactViewModel.getContactByName("%" + searchString + "%");
    ArrayList<DatabaseContacts> contactsArrayList = new ArrayList<>();
    if (searchedContacts !=  null){
        contactsArrayList.addAll(searchedContacts);
        contactsAdapter.refreshMyList(contactsArrayList);
    }
}

and this is called from an on search query text changed method in my onCreateOptionsMenu :

        @Override
        public boolean onQueryTextChange(String newText) {
            try {
                searchDatabase(newText);
            } catch (ExecutionException e) {
                e.printStackTrace();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return false;
        }

but it just does nothing my original recyclerview contents never change any ideas?

like image 350
martinseal1987 Avatar asked Jul 03 '18 12:07

martinseal1987


People also ask

How do I use live data in ViewModel?

Use LiveData for the app's data (word, word count and the score) in the Unscramble app. Add observer methods that get notified when the data changes, update the scrambled word text view automatically. Write binding expressions in the layout file, which are triggered when the underlying LiveData is changed.

What is live data and ViewModel in Android?

ViewModel : Provides data to the UI and acts as a communication center between the Repository and the UI. Hides the backend from the UI. ViewModel instances survive device configuration changes. LiveData : A data holder class that follows the observer pattern, which means that it can be observed.

How do you encapsulate the live data stored in a ViewModel?

How do you encapsulate the LiveData stored in a ViewModel so that external objects can read data without being able to update it? Inside the ViewModel, change the data type of the property to be LiveData and make it private. Use a backing property to expose a read-only property of type MutableLiveData.

Is live data deprecated in Android?

Starts observing this LiveData and represents its values via State . Starts observing this LiveData and represents its values via State . This function is deprecated. This extension method is not required when using Kotlin 1.4.


1 Answers

you can use Transformation.switchMap to do search operations.

  1. In viewmodel create MutableLiveData which has latest search string.

  2. Inside viewmodel use:

    LiveData<Data> data = 
    LiveDataTransformations.switchMap(searchStringLiveData, string ->  
    repo.loadData(string)))
  1. Return the above live data to activity so it can observe and update view.
like image 185
Rohit Avatar answered Oct 11 '22 10:10

Rohit