Я создаю приложение для Android, которое будет хранить списки значений, например. значения температуры в разное время под определенным пользователем именем. Я намереваюсь использовать SQLite для хранения значений, и я прочитал, что использование Room предоставит ему уровень ORM, поэтому я использовал его. Но затем я столкнулся с исключением, в котором говорилось, что я не могу открыть соединение с базой данных из основного потока, поэтому я попытался использовать LiveData для вставки и извлечения. Теперь у меня 2 стола. Я просто пытаюсь показать их структуру без синтаксической точности:
**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
Первоначально я думал о том, чтобы не применять отношения внешнего ключа и просто получить сгенерированный ключ, когда я вставляю объект PLACE_DETAILS, как это делает Hibernate, и использовать его при дальнейших вставках в таблицу TEMPERATURE_DETAILS. Однако из этого вопроса:
API комнаты - Как получить недавно вставленные сгенерированный идентификатор объекта?
Я обнаружил, что сам метод DAO должен возвращать длинное значение, представляющее сгенерированный идентификатор.
@Insert
long insertPlaceDetails(PlaceDetails placeDetails);
Однако AsyncTask, который выполняется в ViewModel, должен переопределить метод doInBackground (), который имеет Void в качестве возврата.
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;
}
}
}
Итак, как я могу получить сгенерированный идентификатор в моем коде? Кроме того, если LiveData не сможет предоставить мне это значение и отношения, то как мне вставить значения в таблицу TEMPERATURE_DETAILS на основе внешнего ключа, который был автоматически сгенерирован в таблице PLACE_DETAILS? Во всех обучающих материалах в Интернете приводятся примеры, в которых идентификатор присваивается вручную.
ИЗМЕНИТЬ
Согласно предложениям, данным anhtuannd, я изменил свой класс VieModel. Но возвращаемое значение всегда -1. Это само по себе показывает, что в базу данных ничего не вставляется. У меня есть разрешение WRITE_EXTERNAL_STORAGE в моем манифесте. Требуется ли что-нибудь еще для того, чтобы это работало?
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);
}
}
}