Как получить автоматически сгенерированный идентификатор из комнаты при использовании LiveData?

Я создаю приложение для 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);
    }
}
}

person supriyo_basak    schedule 02.08.2018    source источник


Ответы (1)


Я думаю, вы можете получить идентификатор, используя функцию обратного вызова в 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
}
person anhtuannd    schedule 02.08.2018
comment
Метод onPlaceInserted () находится вне статического класса AsyncTask. На него нельзя ссылаться изнутри в статическом контексте. - person supriyo_basak; 02.08.2018
comment
Спасибо, просто удалите ключевое слово static или добавьте новый обратный вызов в конструктор AsyncTask. - person anhtuannd; 02.08.2018
comment
Пожалуйста, проверьте мою правку. У меня все еще есть проблемы. - person supriyo_basak; 02.08.2018
comment
Убедитесь, что после insertId = placeDatabase.daoAccess().insertPlaceDetails(place); insertId отличается на -1 - person anhtuannd; 06.08.2018