使用 LiveData 时如何从 Room 检索自动生成的 ID?
How to retrieve auto generated ID from Room when using LiveData?
我正在创建一个 Android 应用程序来存储值列表,例如。特定用户定义名称下不同时间的温度值。我打算使用 SQLite 来存储值,并且我读到使用 Room 会为其提供一个 ORM 层,所以我使用了它。但是后来我 运行 进入了一个异常,基本上说我无法从主线程打开数据库连接,所以我尝试使用 LiveData 进行插入和检索。现在我有 2 tables。我只是想在语法上不准确的情况下展示它们的结构:
**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 所做的那样,并在进一步插入 [=34= 时使用它] table。然而,从这个问题:
我发现 DAO 方法本身需要 return 一个表示生成的 ID 的长值。
@Insert
long insertPlaceDetails(PlaceDetails placeDetails);
但是,在ViewModel中运行的AsyncTask需要重写return.
的doInBackground()方法
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;
}
}
}
那么我如何才能在我的代码中实际检索生成的 ID?此外,如果 LiveData 无法为我提供此值并且关系是可行的方法,那么我还如何根据已经自动设置的外键在 TEMPERATURE_DETAILS table 中插入值- 在 PLACE_DETAILS table 中生成?网络上的所有教程都给出了手动给出 id 的示例。
编辑
根据anhtuannd的建议修改了我的VieModelclass。但是被 returned 的值总是-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);
}
}
}
我觉得你可以通过onPostExecute中的回调函数获取ID:
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
}
我正在创建一个 Android 应用程序来存储值列表,例如。特定用户定义名称下不同时间的温度值。我打算使用 SQLite 来存储值,并且我读到使用 Room 会为其提供一个 ORM 层,所以我使用了它。但是后来我 运行 进入了一个异常,基本上说我无法从主线程打开数据库连接,所以我尝试使用 LiveData 进行插入和检索。现在我有 2 tables。我只是想在语法上不准确的情况下展示它们的结构:
**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 所做的那样,并在进一步插入 [=34= 时使用它] table。然而,从这个问题:
我发现 DAO 方法本身需要 return 一个表示生成的 ID 的长值。
@Insert
long insertPlaceDetails(PlaceDetails placeDetails);
但是,在ViewModel中运行的AsyncTask需要重写return.
的doInBackground()方法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;
}
}
}
那么我如何才能在我的代码中实际检索生成的 ID?此外,如果 LiveData 无法为我提供此值并且关系是可行的方法,那么我还如何根据已经自动设置的外键在 TEMPERATURE_DETAILS table 中插入值- 在 PLACE_DETAILS table 中生成?网络上的所有教程都给出了手动给出 id 的示例。
编辑
根据anhtuannd的建议修改了我的VieModelclass。但是被 returned 的值总是-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);
}
}
}
我觉得你可以通过onPostExecute中的回调函数获取ID:
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
}