I am using room persistence library for save some data and get these data.
Firstly I insert some data to room and after that I try to get inserted data in another fragment. But first time it is empty, after opening fragment second time it shows data. What I forget?
#Database(entities = {Cart.class}, version = 1)
public abstract class AppDatabase extends RoomDatabase {
private static AppDatabase INSTANCE;
public abstract CartDao m=CartDao();
public static synchronized AppDatabase getInstance(Context ctx) {
if (INSTANCE == null)
INSTANCE = Room.databaseBuilder(ctx.getApplicationContext(),
AppDatabase.class, "db")
.fallbackToDestructiveMigration()
.enableMultiInstanceInvalidation()
.build();
return INSTANCE;
}
}
public class CartRepository {
private Application application;
private static CartRepository CartRepository;
private CartDao mCartDao;
private CartRepository(Application application) {
this.application = application;
AppDatabase db;
db = AppDatabase.getInstance(application);
mCartDao = db.mCartDao();
}
public synchronized static CartRepository getInstance(Application application) {
if (CartRepository == null) {
CartRepository = new CartRepository(application);
}
return CartRepository;
}
public void addCart(Cart cart) {
InsertAsyncTask task = new InsertAsyncTask(mCartDao);
task.execute(cart);
}
public List<Cart> getCartList() throws ExecutionException, InterruptedException {
return new GetAllCartAsyncTask(mCartDao).execute().get();
}
private static class InsertAsyncTask extends AsyncTask<Cart, Void, Void> {
private CartDao asyncTaskDao;
InsertAsyncTask(CartDao dao) {
asyncTaskDao = dao;
}
#Override
protected Void doInBackground(final Cart... result) {
asyncTaskDao.addCart(result[0]);
return null;
}
}
private static class GetAllCartAsyncTask extends AsyncTask<Void, Void, List<Cart>> {
private CartDao asyncTaskDao;
GetAllCartAsyncTask(CartDao dao) {
asyncTaskDao = dao;
}
#Override
protected List<Cart> doInBackground(Void... voids) {
return asyncTaskDao.getCartList();
}
}
}
FirstFragment
mCartRepository = CartRepository.getInstance(getActivity().getApplication());
mCartRepository .addCart(cart);
SecondFragment
mCartRepository = CartRepository.getInstance(getActivity().getApplication());
List<Cart> cartList = mCartRepository.getCartList();
// cartList.size is 0 after inserting, only after start fragment again it shows data
if (cartList.size() > 0) {
mList.addAll(cartList);
item_id = cartList.get(0).getItem_id();
}
Related
In my code below I'm getting rowId. I've read that it's also possible to get the last inserted row id from #Insert directly. In my code I changed void insert to long and tried many other things as in examples I found on the internet, but every time I get errors. Would you like to provide me a code/solution to get the row/user ID from #Insert?
#Dao
public interface UserDao {
#Insert
void insert(UserEntity userEntity);
#Update
void update(UserEntity userEntity);
#Delete
void delete(UserEntity userEntity);
#Query("DELETE FROM user_table")
void deleteAllUsers();
#Query("SELECT * FROM user_table")
LiveData<List<UserEntity>> getAllUsers();
// ====== from here ======
#Query("SELECT * FROM user_table")
LiveData<UserEntity> getRowId();
// ====== till here ======
}
Entity
#Entity(tableName = "user_table")
public class UserEntity {
#PrimaryKey(autoGenerate = true)
private int id;
private String userName;
private String userTelephoneNumber;
public UserEntity(String userName, String userTelephoneNumber) {
this.userName = userName;
this.userTelephoneNumber = userTelephoneNumber;
}
public void setId(int id) {
this.id = id;
}
public int getId() {
return id;
}
public String getUserName() {
return userName;
}
public String getUserTelephoneNumber() {
return userTelephoneNumber;
}
}
Repository
public class UserRepository {
private UserDao userDao;
private LiveData<List<UserEntity>> allUsers;
public UserRepository(Application application) {
HandymanDatabase handymanDatabase = HandymanDatabase.getInstance(application);
userDao = handymanDatabase.userDao();
allUsers = userDao.getAllUsers();
}
public void insert(UserEntity userEntity) {
new InsertUserAsyncTask(userDao).execute(userEntity);
}
public void update(UserEntity userEntity) {
new UpdateUserAsyncTask(userDao).execute(userEntity);
}
public void delete(UserEntity userEntity) {
new DeleteUserAsyncTask(userDao).execute(userEntity);
}
public void deleteAllUsers() {
new DeleteAllUsersAsyncTask(userDao).execute();
}
public LiveData<List<UserEntity>> getAllUsers() {
return allUsers;
}
// ====== from here ======
public LiveData<UserEntity> getRowId() {
return userDao.getRowId();
}
// ====== till here ======
private static class InsertUserAsyncTask extends AsyncTask<UserEntity, Void, Void> {
private UserDao userDao;
private InsertUserAsyncTask(UserDao userDao) {
this.userDao = userDao;
}
#Override
protected Void doInBackground(UserEntity... userEntities) {
userDao.insert(userEntities[0]);
return null;
}
}
private static class UpdateUserAsyncTask extends AsyncTask<UserEntity, Void, Void> {
private UserDao userDao;
private UpdateUserAsyncTask(UserDao userDao) {
this.userDao = userDao;
}
#Override
protected Void doInBackground(UserEntity... userEntities) {
userDao.update(userEntities[0]);
return null;
}
}
private static class DeleteUserAsyncTask extends AsyncTask<UserEntity, Void, Void> {
private UserDao userDao;
private DeleteUserAsyncTask(UserDao userDao) {
this.userDao = userDao;
}
#Override
protected Void doInBackground(UserEntity... userEntities) {
userDao.delete(userEntities[0]);
return null;
}
}
private static class DeleteAllUsersAsyncTask extends AsyncTask<Void, Void, Void> {
private UserDao userDao;
private DeleteAllUsersAsyncTask(UserDao userDao) {
this.userDao = userDao;
}
#Override
protected Void doInBackground(Void... voids) {
userDao.deleteAllUsers();
return null;
}
}
}
ViewModel
public UserViewModel(#NonNull Application application) {
super(application);
userRepository = new UserRepository(application);
allUsers = userRepository.getAllUsers();
}
public void insert(UserEntity userEntity) {
userRepository.insert(userEntity);
}
public void update(UserEntity userEntity) {
userRepository.update(userEntity);
}
public void delete(UserEntity userEntity) {
userRepository.delete(userEntity);
}
public void deleteAllUsers() {
userRepository.deleteAllUsers();
}
public LiveData<List<UserEntity>> getAllUsers() {
return allUsers;
}
// ====== from here ======
public LiveData<UserEntity> getRowId() {
return userRepository.getRowId();
}
// ====== till here ======
}
Fragment/Activity
public class UserFavoritesFragment extends Fragment {
private static final String TAG = "UserFavoritesFragment";
private UserViewModel userViewModel;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = getLayoutInflater().inflate(R.layout.fragment_user_favorites, container, false);
final TextView textViewUserName = view.findViewById(R.id.textViewUserName);
TextView textViewUserPhone = view.findViewById(R.id.textViewUserPhone);
userViewModel = new ViewModelProvider(this).get(UserViewModel.class);
// ====== from here ======
userViewModel.getRowId().observe(getViewLifecycleOwner(), new Observer<UserEntity>() {
#Override
public void onChanged(UserEntity userEntity) {
long rowId = userEntity.getId();
Log.d(TAG, "onChanged: " + rowId);
}
});
// ====== till here ======
return view;
}
}
You can do that using a listener interface that has a callback that accepts a long value of the inserted row id in the database.
Listener Interface
public interface NewIdListener {
void onInsert(long id);
}
Dao
#Dao
public interface UserDao {
#Insert
long insert(UserEntity userEntity); // return id of the inserted userEntity
}
Repository
public class UserRepository {
private Executor mExecutor = Executors.newSingleThreadExecutor();
private UserDao userDao;
...
public void insertUserEntity(final UserEntity entity, final NewIdListener listener) {
mExecutor.execute(new Runnable() {
#Override
public void run() {
listener.onInsert(userDao.insert(entity));
}
});
}
ViewModel
public void insertUserEntity(UserEntity entity, NewIdListener listener) {
userRepository.insertUserEntity(entity, listener);
}
Activity
userViewModel.insertUserEntity(new UserEntity("User Name", "12345678"), new NewIdListener() {
#Override
public void onInsert(final long id) {
requireActivity().runOnUiThread(new Runnable() {
#Override
public void run() {
Toast.makeText(requireActivity(), "Id: " + id, Toast.LENGTH_SHORT).show();
}
});
}
});
Note: For background thread, I've used Executor instead of AsyncTask as AsyncTask is deprecated now.
I'm trying to use Room database in my Quiz application.
I couldn't get list of questions from database. here is the code I'm using :
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
final View rootView = inflater.inflate(R.layout.new_exam, container, false);
queViewModel=ViewModelProviders.of(this).get(QueViewModel.class);
queViewModel.getQuizList(examType).observe(this, new Observer<List<QueEnt>>() {
#Override
public void onChanged(List<QueEnt> queEnts) {
Log.e(TAG, "onChanged is called!"); // this line never shows in the Logcat
questionsList2 = queEnts;
}
});
and this is the ViewModel :
public class QueViewModel extends AndroidViewModel {
private QueRepository repository;
private LiveData<List<QueEnt>> quesList;
public QueViewModel(#NonNull Application application) {
super(application);
repository=new QueRepository(application);
quesList=repository.getQues();
}
public void insert(QueEnt queEnt){
repository.insert(queEnt);
}
public void delete(QueEnt queEnt){
repository.delete(queEnt);
}
public LiveData<List<QueEnt>> getQuizList(int examtype){
Log.e(TAG,"returning a list"); // this appears in the Logcat
return quesList;
}
}
The error I get is
Invalid index 0, size is 0
on questionsList2 , of course because the list was never populated. The onChanged method is not called, as it seems from the Logcat.
How can I fix this ?
Edit :
QueRepository file:
public class QueRepository {
private QueDao queDao;
private LiveData<List<QueEnt>> ques;
public QueRepository(Application application) {
QueDatabase database = QueDatabase.getInstance(application);
queDao = database.queDao();
ques = queDao.getQuesAll();
}
public void insert(QueEnt queEnt) {
new InsertQAsync(queDao).execute(queEnt);
}
public void update(QueEnt queEnt) {
new UpdateQAsync(queDao).execute(queEnt);
}
public void delete(QueEnt queEnt) {
new DeleteQAsync(queDao).execute(queEnt);
}
public LiveData<List<QueEnt>> getQues() {
return ques;
}
private static class InsertQAsync extends AsyncTask<QueEnt, Void, Void> {
private QueDao queDao;
private InsertQAsync(QueDao queDao) {
this.queDao = queDao;
}
#Override
protected Void doInBackground(QueEnt... queEnts) {
queDao.insert(queEnts[0]);
return null;
}
}
private static class UpdateQAsync extends AsyncTask<QueEnt, Void, Void> {
private QueDao queDao;
private UpdateQAsync(QueDao queDao) {
this.queDao = queDao;
}
#Override
protected Void doInBackground(QueEnt... queEnts) {
queDao.update(queEnts[0]);
return null;
}
}
private static class DeleteQAsync extends AsyncTask<QueEnt, Void, Void> {
private QueDao queDao;
private DeleteQAsync(QueDao queDao) {
this.queDao = queDao;
}
#Override
protected Void doInBackground(QueEnt... queEnts) {
queDao.delete(queEnts[0]);
return null;
}
}
}
And QueDao :
#Dao
public interface QueDao {
#Insert
void insert(QueEnt queEnt);
#Update
void update(QueEnt queEnt);
#Delete
void delete(QueEnt queEnt);
#Query("SELECT * FROM questions LIMIT 30" )
LiveData<List<QueEnt>> getQuesAll();
}
And Database :
#Database(entities = {QueEnt.class}, version = 1)
public abstract class QueDatabase extends RoomDatabase {
public static QueDatabase instance;
public static synchronized QueDatabase getInstance(Context context) {
if (instance == null) {
instance = Room.databaseBuilder(context.getApplicationContext(), QueDatabase.class, "que_database")
.fallbackToDestructiveMigration()
.addCallback(roomCallback)
.build();
}
return instance;
}
public abstract QueDao queDao();
private static RoomDatabase.Callback roomCallback = new RoomDatabase.Callback() {
#Override
public void onCreate(#NonNull SupportSQLiteDatabase db) {
super.onCreate(db);
new PopulateDbAsync(instance).execute();
}
};
private static class PopulateDbAsync extends AsyncTask<Void, Void, Void> {
private QueDao queDao;
private PopulateDbAsync(QueDatabase db) {
queDao = db.queDao();
}
#Override
protected Void doInBackground(Void... voids) {
queDao.insert(new QueEnt(91, 93, "Question 1?", " Answer 1", "Answer2 ", "Answer 3 ", " Answer4 ", 2, 2, 1,0,0,0,0,0,"","","","",""));
queDao.insert(new QueEnt(93, 95, "Question 2?", " Answer 1", "Answer2 ", "Answer 3 ", " Answer4 ", 3, 2, 4,0,0,0,0,0,"","","","",""));
return null;
}
}
}
Hi I'm doing an app and I made the database but I don't know how to read it to show in a listview for example I have a table CategoriaEntradas and I need to show all the data in a listview but I don't understand very well how it works all the classes
This is my Dao class
#Dao
public interface CategoriaEntradasDao {
#Insert
void insert(CategoriaEntradas categoriaEntradas);
#Update
void update(CategoriaEntradas categoriaEntradas);
#Delete
void delete(CategoriaEntradas categoriaEntradas);
#Query("DELETE FROM CategoriaEntradas")
void deleteAll();
#Query("SELECT * FROM CategoriaEntradas")
LiveData<List<CategoriaEntradas>> getAll();
#Query("SELECT * FROM CategoriaEntradas WHERE IdCategoria =:Id")
LiveData<CategoriaEntradas> getOne(int Id);
}
This is my Entity class
#Entity(tableName = "CategoriaEntradas")
public class CategoriaEntradas {
#PrimaryKey(autoGenerate = true)
#NonNull
#ColumnInfo(name = "IdCategoria")
private Integer _idCategoria;
#NonNull
#ColumnInfo(name = "Name")
private String _name;
#NonNull
#ColumnInfo(name = "Image")
private String _image;
public CategoriaEntradas(#NonNull String name, #NonNull String image) { _name = name; _image = image;}
public void set_idCategoria(Integer _idCategoria){
this._idCategoria = _idCategoria;
}
#NonNull
public Integer getIdCategoria() {
return _idCategoria;
}
#NonNull
public String getName() {
return _name;
}
#NonNull
public String getImage() {
return _image;
}
}
My Repository class
public class CategoriaEntradasRepository {
private CategoriaEntradasDao categoriaEntradasDao;
private LiveData<List<CategoriaEntradas>> listLiveData;
public CategoriaEntradasRepository(Application application) {
Database db = Database.getDatabase(application);
categoriaEntradasDao = db.categoriaEntradasDao();
listLiveData = categoriaEntradasDao.getAll();
}
public LiveData<List<CategoriaEntradas>> getAll() {
return listLiveData;
}
public LiveData<CategoriaEntradas> getOne(int Id) {
return categoriaEntradasDao.getOne(Id);
}
public void insert (CategoriaEntradas categoriaEntradas) {
new CategoriaEntradasRepository.insertAsyncTask(categoriaEntradasDao).execute(categoriaEntradas);
}
private static class insertAsyncTask extends AsyncTask<CategoriaEntradas, Void, Void> {
private CategoriaEntradasDao entradasDao;
insertAsyncTask(CategoriaEntradasDao dao) {
entradasDao = dao;
}
#Override
protected Void doInBackground(final CategoriaEntradas... params) {
entradasDao.insert(params[0]);
return null;
}
}
public void update(final CategoriaEntradas categoriaEntradas){
new CategoriaEntradasRepository.updateAsyncTask(categoriaEntradasDao).execute(categoriaEntradas);
}
private static class updateAsyncTask extends AsyncTask<CategoriaEntradas, Void, Void>{
private CategoriaEntradasDao entradasDao;
updateAsyncTask(CategoriaEntradasDao dao) {
entradasDao = dao;
}
#Override
protected Void doInBackground(final CategoriaEntradas... params){
entradasDao.update(params[0]);
return null;
}
}
public void delete(final CategoriaEntradas categoriaEntradas) {
new CategoriaEntradasRepository.deleteAsyncTask(categoriaEntradasDao).execute(categoriaEntradas);
}
public void delete(final int Id) {
final LiveData<CategoriaEntradas> categoriaEntradas = getOne(Id);
if (categoriaEntradas != null) {
new CategoriaEntradasRepository.deleteAsyncTask(categoriaEntradasDao).execute(categoriaEntradas.getValue());
}
}
private static class deleteAsyncTask extends AsyncTask<CategoriaEntradas, Void, Void>{
private CategoriaEntradasDao entradasDao;
deleteAsyncTask(CategoriaEntradasDao dao) {
entradasDao = dao;
}
#Override
protected Void doInBackground(final CategoriaEntradas... params){
entradasDao.delete(params[0]);
return null;
}
}
}
And my ViewModel class
public class CategoriaEntradasViewModel extends AndroidViewModel {
private CategoriaEntradasRepository repository;
private LiveData<List<CategoriaEntradas>> listLiveData;
public CategoriaEntradasViewModel (Application application) {
super(application);
repository = new CategoriaEntradasRepository(application);
listLiveData = repository.getAll();
}
public LiveData<List<CategoriaEntradas>> getAll() { return listLiveData; }
public LiveData<CategoriaEntradas> getOne(int Id) { return repository.getOne(Id); }
public void insert(CategoriaEntradas categoriaEntradas) { repository.insert(categoriaEntradas); }
public void update(CategoriaEntradas categoriaEntradas){ repository.update(categoriaEntradas);}
public void delete(CategoriaEntradas categoriaEntradas) {repository.delete(categoriaEntradas);}
public void delete(int Id) {repository.delete(Id);}
}
Try this at your Activity or fragment that have your listview.
CategoriaEntradasViewModel mViewModel = ViewModelProviders.of(this).get(CategoriaEntradasViewModel.class);
mViewModel.getAll().observe(this, new Observer<List<CategoriaEntradas>>() {
#Override
public void onChanged(List<CategoriaEntradas> categoriaEntradas) {
adapter = new YourListViewAdapter(this, categoriaEntradas);
listview.setAdapter(adapter);
}
}
Yes, if you have custom list item view. Its similar to array adapter.
I have the CidVo class:
#Entity
public class CidVo implements Serializable {
private static final long serialVersionUID = 6128323407787450445L;
#NonNull
#PrimaryKey
private String idCid;
private String dsCid;
//private StatusType idStatus;
public CidVo() {
super();
}
public String getIdCid() {
return idCid;
}
public void setIdCid(String idCid) {
this.idCid = idCid;
}
public String getDsCid() {
return dsCid;
}
public void setDsCid(String dsCid) {
this.dsCid = dsCid;
}
/*public StatusType getIdStatus() {
return idStatus;
}
public void setIdStatus(StatusType idStatus) {
this.idStatus = idStatus;
} */
}
The DAO class:
#Dao
public interface CIDDao {
#Insert(onConflict = OnConflictStrategy.REPLACE)
void insertAllCID(ArrayList<CidVo>... cidVos);
}
I get a list of objects, via JSON. And I would like to save it in the database.
But, I get this return error when trying to compile:
Error:Entity class must be annotated with #Entity
E:\workspace_android_studio\app_atendimento_branch_test\app\src\main\java\br\com\sisteplan\app\atendimento\Model\CIDDao.java
Error:(19, 43) error: Type of the parameter must be a class annotated
with #Entity or a collection/array of it.
How to solve this question?
The following is the postExecute:
#Override
protected void onPostExecute(AsyncTaskResult<Retorno> respAtestadoVo) {
super.onPostExecute(respAtestadoVo);
if (respAtestadoVo.getExceptionResult() == null) {
RetornoCid retornoCid = (RetornoCid) respAtestadoVo.getResult();
ArrayList<CidVo> cidVos = (ArrayList<CidVo>) retornoCid.getRetorno();
appDataBase.getCidDao().insertAllCID(cidVos);
Toast.makeText(context, "Sucesso", Toast.LENGTH_SHORT).show();
}
}
Instance:
#Database(entities = {CidVo.class}, version = 1)
public abstract class AppDataBase extends RoomDatabase {
public abstract CIDDao getCidDao();
private static AppDataBase appDataBase;
public static AppDataBase getInstance(Context context){
if(null == appDataBase){
appDataBase = buildDataBaseInstance(context);
}
return appDataBase;
}
private static AppDataBase buildDataBaseInstance(Context context){
return Room.databaseBuilder(context,
AppDataBase.class,
"app_database")
.allowMainThreadQueries().build();
}
private void cleanUp(){
appDataBase = null;
}
}
The reason is a vararg notation here void insertAllCID(ArrayList<CidVo>... cidVos);
You're trying to insert an array of array lists.
So, just replace it with
void insertAllCID(List<CidVo> cidVos);
Also, it's better to use interfaces over implementations, when you're working with collections. So, you can change this part
RetornoCid retornoCid = (RetornoCid) respAtestadoVo.getResult();
ArrayList<CidVo> cidVos = (ArrayList<CidVo>) retornoCid.getRetorno();
to this
RetornoCid retornoCid = (RetornoCid) respAtestadoVo.getResult();
List<CidVo> cidVos = new ArrayList(retornoCid.getRetorno());
Working with room persistence, when trying to get the database to insert or make select in the items, the error appears:
AppDataBase.getMovieDao()' on a null object reference
The classes related to the process are as follows:
AppDataBase class:
#Database(entities = {Movies.class}, version = 1)
public abstract class AppDataBase extends RoomDatabase {
public static final String DB_NAME = "Movies";
private static AppDataBase INSTANCE;
public static AppDataBase getDataBase(Context context){
if (INSTANCE == null){
INSTANCE = Room.databaseBuilder(context.getApplicationContext(),AppDataBase.class,DB_NAME).build();
}
return INSTANCE;
}
public abstract MovieDao getMovieDao();
}
Dao Class:
#Dao
public interface MovieDao {
#Insert
void insertAll(Movies movies);
#Update
void updateAll(Movies... notes);
#Query("SELECT * FROM moviestb")
List<Movies> getAll();
#Delete
void deleteAll(Movies... notes);
}
Entity class:
#Entity(tableName = "moviestb")
public class Movies {
#PrimaryKey(autoGenerate = true)
#ColumnInfo(name = "idmovie")
private long id;
#ColumnInfo(name = "titlemovie")
private String titlemovie;
........
}
Searching for the registrations:
public void loadFromDB(){
db.getDataBase(view.getContext());
if(db.getMovieDao().getAll().size() > 0){
adapter.setResults(db.getMovieDao().getAll());
}else{
Toast.makeText(view.getContext(),"Não há filmes cadastrados",Toast.LENGTH_SHORT).show();
view.getActivity().finish();
}
}
Insert:
public View.OnClickListener onSaveClick(final String plot, final String diretor, final String autor,
final String nome, final String tipo, final String ano, final String ator, final String imdb) {
return new View.OnClickListener() {
#Override
public void onClick(View itemView) {
db.getDataBase(view.getContext());
Movies movies = new Movies(nome,plot,imdb,"",ator,ano,tipo,diretor,autor);
new InsertAsyncTask(db).execute(movies);
}
};
}
private class InsertAsyncTask extends AsyncTask<Movies,Void,Void>{
private AppDataBase db;
public InsertAsyncTask(AppDataBase appDataBase) {
db = appDataBase;
}
#Override
protected Void doInBackground(Movies... params) {
db.getMovieDao().insertAll(params[0]);
return null;
}
}
Searching all:
public void loadFromDB(){
db.getDataBase(view.getContext());
if(db.getMovieDao().getAll().size() > 0){
adapter.setResults(db.getMovieDao().getAll());
}else{
Toast.makeText(view.getContext(),"Não há filmes cadastrados",Toast.LENGTH_SHORT).show();
view.getActivity().finish();
}
}
The crash occurs while fetching the database, what am I doing wrong? thank you!
db is null, apparently. Your question does not show where you ever assign it a value.
Please note that getDataBase() is a static method. Perhaps you should have a db=AppDataBase.getDataBase() statement somewhere.