I am new at the room database in android and I want to insert data into the room, but before inserting I want to check if the item already exists in the database or not. I am using these codes(News and Article are the same it is just naming problem):
My Dao
package com.example.newsapp.models;
import androidx.lifecycle.LiveData;
import androidx.room.Dao;
import androidx.room.Insert;
import androidx.room.OnConflictStrategy;
import androidx.room.Query;
import com.example.newsapp.operations.Article;
import java.util.List;
@Dao
public interface SavedNewsDAO {
@Insert(onConflict = OnConflictStrategy.REPLACE)
void insert(Article article);
@Query("DELETE FROM saved_articles")
void deleteAll();
@Query("DELETE FROM saved_articles where id =:id ")
void removeNews(int id);
@Query("SELECT * FROM saved_articles")
LiveData<List<Article>> getAll();
@Query("select Count() from saved_articles where title =:title and content =:content and description =:description")
int checkArticle(String title, String content, String description);
}
I want to get number of items in the database with checkArticle method.
My Repository
package com.example.newsapp.models;
import android.app.Application;
import androidx.lifecycle.LiveData;
import com.example.newsapp.operations.Article;
import java.util.List;
public class SavedArticlesRepository {
private final LiveData<List<Article>> allArticles;
private final SavedNewsDAO savedNewsDAO;
SavedArticlesRepository(Application application) {
SavedNewsRoomDatabase db = SavedNewsRoomDatabase.getDatabase(application);
savedNewsDAO = db.savedNewsDAO();
allArticles = savedNewsDAO.getAll();
}
LiveData<List<Article>> getAllArticles() {
return allArticles;
}
void insert(Article article) {
SavedNewsRoomDatabase.databaseWriterExecutor.execute(() -> savedNewsDAO.insert(article));
}
void checkItem(Article article) {
SavedNewsRoomDatabase.databaseWriterExecutor.execute(() -> {
savedNewsDAO.checkArticle(article.title, article.content, article.description);
});
}
}
and this is my View Model
package com.example.newsapp.models;
import android.app.Application;
import androidx.lifecycle.AndroidViewModel;
import androidx.lifecycle.LiveData;
import com.example.newsapp.operations.Article;
import java.util.List;
public class SavedNewsViewModel extends AndroidViewModel {
private final SavedArticlesRepository savedArticlesRepository;
private final LiveData<List<Article>> allArticles;
public SavedNewsViewModel(Application application) {
super(application);
savedArticlesRepository = new SavedArticlesRepository(application);
allArticles = savedArticlesRepository.getAllArticles();
}
public LiveData<List<Article>> getAllArticles() {
return allArticles;
}
public void insert(Article article) {
savedArticlesRepository.insert(article);
}
public void checkArticle(Article article) {
savedArticlesRepository.checkItem(article);
}
}
The problem is that I can't imagine how can I use checkArticle method in ViewModel and Repository classes like getAll method. As I understand I must chain these methods to each-others. And I want to check in this method:
savedNewsViewModel = new ViewModelProvider(this).get(SavedNewsViewModel.class);
saveArticleButton.setOnClickListener(v -> {
Article article = new Article();
article.title = intent.getStringExtra("title");
article.description = intent.getStringExtra("description");
article.content = intent.getStringExtra("content");
article.urlToImage = intent.getStringExtra("image");
savedNewsViewModel.insert(article);
Toast.makeText(this, "Article saved successfully", Toast.LENGTH_SHORT).show();
});
I have looked other questions, but I couldn't get it
You need to observe the value which you get from your checkArticle
method.
Use MutableLiveData in the following way:
public class SavedArticlesRepository {
....
LiveData<Integer> checkItem(Article article) {
MutableLiveData<Integer> data = MutableLiveData();
SavedNewsRoomDatabase.databaseWriterExecutor.execute(() -> {
int count = savedNewsDAO.checkArticle(article.title, article.content, article.description);
data.postValue(count);
});
return data;
}
}
Now in your viewmodel, also extend the checkArticle
with LiveData
public LiveData<Integer> checkArticle(Article article) {
return savedArticlesRepository.checkItem(article);
}
In your fragment or activity observe this method:
saveArticleButton.setOnClickListener(v -> {
Article article = new Article();
article.title = intent.getStringExtra("title");
article.description = intent.getStringExtra("description");
article.content = intent.getStringExtra("content");
article.urlToImage = intent.getStringExtra("image");
savedNewsViewModel.checkArticle.observe(getViewLifeCycleOwner(), new Observer{ count ->
if(count > 0){
Toast.makeText(this, "Article already exists", Toast.LENGTH_SHORT).show();
} else {
savedNewsViewModel.insert(article);
Toast.makeText(this, "Article saved successfully", Toast.LENGTH_SHORT).show();
}
});
});
I haven't tested this code, as I don't work with Java anymore. But should work fine. If I can suggest, I'd say learn Kotlin and coroutines. This stuff is so much easier when you're using Kotlin and coroutines.
Leave a comment if you need any more help with this.