I am creating an Android application which would store lists of values, eg. temperature values for different times under a particular user-defined name. I intend to use SQLite for storing the values, and I read that using Room would provide an ORM layer to it, so I used it. But then I ran into an exception which basically said that I cannot open a database connection from the main thread, so I tried using LiveData for insertion and retrieval purposes. Now I have 2 tables. I'm just trying to show the structure of them without being syntactically accurate:
**PLACE_DETAILS**
place_id integer auto_increment
place_name string
latitude double
longitude double
**TEMPERATURE_DETAILS**
temperature_id integer auto_increment
place_id foreign key references place_details(place_id)
time_of_record timestamp
temperature float
Initially, I thought of not enforcing the foreign key relationship and just retrieving the generated key when I insert the PLACE_DETAILS object, like what Hibernate does, and using it in further insertions into the TEMPERATURE_DETAILS table. However, from this question:
Room API - How to retrieve recently inserted generated id of the entity?
I found that the DAO method itself would need to return a long value representing the generated ID.
@Insert
long insertPlaceDetails(PlaceDetails placeDetails);
However, the AsyncTask which runs in the ViewModel needs to override the doInBackground() method which has Void as the return.
public class PlaceDetailsViewModel extends AndroidViewModel {
private final LiveData<List<PlaceDetails>> placeDetailsList;
private PlaceDatabase placeDatabase;
public PlaceDetailsViewModel(@NonNull Application application) {
super(application);
placeDatabase = PlaceDatabase.getDatabase(this.getApplication());
placeDetailsList = placeDatabase.daoAccess().fetchAllPlaceDetails();
}
public LiveData<List<PlaceDetails>> getPlaceDetailsList() {
return placeDetailsList;
}
public void addPlace(final PlaceDetails placeDetails) {
Log.d("Adding", "Place: " + placeDetails.getPlaceName());
new addAsyncTask(placeDatabase).execute(placeDetails);
}
private static class addAsyncTask extends AsyncTask<PlaceDetails, Void, Void> {
private PlaceDatabase placeDatabase;
addAsyncTask(PlaceDatabase placeDatabase) {
this.placeDatabase = placeDatabase;
}
@Override
protected Void doInBackground(PlaceDetails... placeDetails) {
placeDatabase.daoAccess().insertPlaceDetails(placeDetails[0]);
return null;
}
}
}
So how could I actually retrieve the generated ID in my code? Also, if LiveData won't be able to provide me this value and relationship is the way to go, then also how do I insert values in the TEMPERATURE_DETAILS table based on the foreign key which has been auto-generated in the PLACE_DETAILS table? All the tutorials in the web give examples where they have given the id manually.
EDIT
According to the suggestions given by anhtuannd, I modified my VieModel class. But the value which is being returned is always -1. That itself shows that nothing is being inserted into the database. I have the WRITE_EXTERNAL_STORAGE permission in my manifest. Is anything else required for this to work?
public class PlaceDetailsViewModel extends AndroidViewModel {
private final LiveData<List<PlaceDetails>> placeDetailsList;
private PlaceDatabase placeDatabase;
private long insertId = -1;
public long getInsertId() {
return insertId;
}
public PlaceDetailsViewModel(@NonNull Application application) {
super(application);
placeDatabase = PlaceDatabase.getDatabase(this.getApplication());
placeDetailsList = placeDatabase.daoAccess().fetchAllPlaceDetails();
}
public LiveData<List<PlaceDetails>> getPlaceDetailsList() {
return placeDetailsList;
}
public void onPlaceInserted(long id) {
insertId = id;
}
public void addPlace(final PlaceDetails placeDetails) {
Log.d("Adding", "Place: " + placeDetails.getPlaceName());
new addAsyncTask(placeDatabase).execute(placeDetails);
}
private class addAsyncTask extends AsyncTask<PlaceDetails, Void, Void> {
private PlaceDatabase placeDatabase;
addAsyncTask(PlaceDatabase placeDatabase) {
this.placeDatabase = placeDatabase;
}
@Override
protected Void doInBackground(PlaceDetails... placeDetails) {
insertId = placeDatabase.daoAccess().insertPlaceDetails(placeDetails[0]);
return null;
}
@Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
onPlaceInserted(insertId);
}
}
}
I think you can get ID by using callback function in onPostExecute:
private static class addAsyncTask extends AsyncTask<PlaceDetails, Void, Void> {
private PlaceDatabase placeDatabase;
private PlaceDetails place;
private int insertId = -1;
addAsyncTask(PlaceDatabase placeDatabase) {
this.placeDatabase = placeDatabase;
}
@Override
protected Void doInBackground(PlaceDetails... placeDetails) {
place = placeDetails[0];
insertId = placeDatabase.daoAccess().insertPlaceDetails(place);
return null;
}
@Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
onPlaceInserted(insertId, place);
}
}
void onPlaceInserted(int id, PlaceDetails place) {
// you get ID here
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.