Home » Android » android – Room query returns null

android – Room query returns null

Posted by: admin June 15, 2020 Leave a comment

Questions:

I’m trying to determine whether an item with a certain ID exists in my database but I keep getting null even though I know it’s in the database. I’m pretty sure I’m defining my query incorrectly but I’m not sure what the issue is. I’ve been looking at Room query examples but haven’t been able to fix the issue. I don’t see any bugs when I run the code except a null pointer exception when I try to print the log for the query.

The query I’m trying to do in DAO looks like this:

    @Query("select filmID from FilmDataModel where filmID = :currentId")
    LiveData<String> inDatabase(String currentId);

My view model has this method to act as a go between the UI and the DAO:

public LiveData<String> inDatabase(String currentID) {
        LiveData<String> filmID = filmDatabase.filmDao().inDatabase(currentID);
        return filmID;
    }

My FilmDataModel object is defined as follows:

@Entity public class FilmDataModel {
    @PrimaryKey(autoGenerate = true)
    public int id;
    @ColumnInfo(name = "posterURL")
    private String posterURL;
    private String releaseDate;
    @ColumnInfo(name = "voterAvg")
    private String voterAvg;
    @ColumnInfo(name = "description")
    private String description;
    @ColumnInfo(name = "title")
    private String title;
    @ColumnInfo(name = "filmID")
    private String filmId;

    public FilmDataModel(String posterURL, String releaseDate, String voterAvg, String description,
                         String title, String filmId) {
        this.posterURL = posterURL;
        this.releaseDate = releaseDate;
        this.voterAvg = voterAvg;
        this.description = description;
        this.title = title;
        this.filmId = filmId;
    }

    public String getPosterURL() {
        return this.posterURL;
    }

    public String getReleaseDate() {
        return releaseDate;
    }

    public String getDescription() {
        return description;
    }

    public String getFilmId() {
        return filmId;
    }

    public String getTitle() {
        return title;
    }

    public String getVoterAvg() {
        return voterAvg;
    } 
}

Then from my Activity I set the following code on a button click:

favoriteButton.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
        Log.d(TAG, "Favorite button pressed.");
        FilmDataModel filmDataModel = new FilmDataModel(posterURL, releaseDate, voterAvg,
                overview, title, id);
        if (favoriteSelected) {
            Log.d(TAG, "Delete Item.");
            favoriteSelected = false;
            favoriteButton.setImageResource(R.drawable.heart_icon_off);
            viewModel.deleteItem(filmDataModel);
        } else {
            Log.d(TAG, "Insert Item.");
            favoriteSelected = true;
            favoriteButton.setImageResource(R.drawable.heart_icon_on);
            viewModel.insertItem(filmDataModel);
            Log.d(TAG, viewModel.inDatabase(id).getValue());
        }
    }
});

It looks like data is inserted into the database and deleted from the database ok based on print statements from the activity and the view model but when I try to run the query and print the filmID I get a null. Can I not do what I’m trying to do from the Activity? Is my query statement incorrect for some reason?

How to&Answers:

From Android Developers documentation:

LiveData is a data holder class that can be observed within a given
lifecycle

which means you will have to register an Observer first in order to receive data updates.

Again, from Android Developers documentation:

Generally, LiveData delivers updates only when data changes, and only
to active observers. An exception to this behavior is that observers
also receive an update when they change from an inactive to an active
state. Furthermore, if the observer changes from inactive to active a
second time, it only receives an update if the value has changed since
the last time it became active.

Here is a possible solution:

favoriteButton.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
        Log.d(TAG, "Favorite button pressed.");
        FilmDataModel filmDataModel = new FilmDataModel(posterURL, releaseDate, voterAvg, overview, title, id);
        if (favoriteSelected) {
            Log.d(TAG, "Delete Item.");                
        } else {
            Log.d(TAG, "Insert Item.");
            favoriteSelected = true;
            favoriteButton.setImageResource(R.drawable.heart_icon_on);
            viewModel.insertItem(filmDataModel);  
            viewModel.inDatabase(id).observe(this, new Observer<String>() {
                @Override
                public void onChanged(@Nullable final String name) {
                   // your code here
                   Log.d(TAG, name.getValue());
                }
            });
        }
    }
});

For more information, see Work with LiveData objects