使用LiveData时如何从Room中检索自动生成的ID?

时间:2018-08-02 03:54:46

标签: android sqlite android-room android-livedata android-viewmodel

我正在创建一个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

最初,我想到不要强制外键关系,而只是像Hibernate那样插入PLACE_DETAILS对象,并在进一步插入TEMPERATURE_DETAILS表中使用它时,才检索生成的键。但是,从这个问题来看:

Room API - How to retrieve recently inserted generated id of the entity?

我发现DAO方法本身需要返回一个表示生成的ID的长值。

@Insert
long insertPlaceDetails(PlaceDetails placeDetails);

但是,在ViewModel中运行的AsyncTask需要重写以Void作为返回值的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无法为我提供此值并且关系是解决方法,那么我又如何根据PLACE_DETAILS表中自动生成的外键在TEMPERATURE_DETAILS表中插入值?网络上的所有教程都提供了一些示例,这些示例中已经手动给出了ID。

编辑

根据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);
    }
}
}

1 个答案:

答案 0 :(得分:2)

我认为您可以通过在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
}