Как добавить элемент в дочернюю сущность со ссылкой на внешний ключ родительской сущности в Android Room? - PullRequest
0 голосов
/ 31 августа 2018

Я пытаюсь написать простое приложение, похожее на Strava, которое будет записывать действия, используя Room Persistence Library

Мои две сущности:

@Entity
public class ActivityRecord {
    @PrimaryKey(autoGenerate = true)
    private long id;
    private Date startTimestamp;
    private Date endTimestamp;

    public ActivityRecord() {
        this.startTimestamp = new Date();
        this.endTimestamp = this.startTimestamp;
    }

    public long getId() {
        return id;
    }

    public void setId(long id) {
        this.id = id;
    }

    public Date getStartTimestamp() {
        return startTimestamp;
    }

    public void setStartTimestamp(Date startTimestamp) {
        this.startTimestamp = startTimestamp;
    }

    public Date getEndTimestamp() {
        return endTimestamp;
    }

    public void setEndTimestamp(Date endTimestamp) {
        this.endTimestamp = endTimestamp;
    }
}

и

@Entity(foreignKeys = @ForeignKey(
    entity = ActivityRecord.class,
    parentColumns = "id",
    childColumns = "recordId",
    onDelete = CASCADE),
    indices = {@Index(value = {"recordId"})})
public class ActivityLocation {

    @PrimaryKey(autoGenerate = true)
    private long id;   
    private double latitude;
    private double longitude;
    private long recordId;


    public ActivityLocation(double latitude, double longitude, long recordId) {
        this.latitude = latitude;
        this.longitude = longitude;
        this.recordId = recordId;
    }

    public long getId() {
        return id;
    }

    public void setId(long id) {
        this.id = id;
    }

    public double getLatitude() {
        return latitude;
    }

    public void setLatitude(double latitude) {
        this.latitude = latitude;
    }

    public double getLongitude() {
        return longitude;
    }

    public void setLongitude(double longitude) {
        this.longitude = longitude;
    }

    public long getRecordId() { return recordId; }

    public void setRecordId(long recordId) { this.recordId = recordId; }
}

Я также создал эти два DAO:

@Dao
public interface ActivityRecordDao {
    @Query("SELECT * FROM ActivityRecord ORDER BY id DESC")
    LiveData<List<ActivityRecord>> getActivityRecords();

    @Query("SELECT * FROM ActivityRecord WHERE id = :id")
    ActivityRecord getActivityRecordById(long id);

    @Query("SELECT * FROM ActivityRecord ORDER BY id DESC LIMIT 1")
    ActivityRecord getLastActivityRecord();

    @Insert
    long setActivityRecord(ActivityRecord record);

    @Update
    void updateActivityRecord(ActivityRecord record);

    @Delete
    void deleteActivityRecord(ActivityRecord record);
}

и:

@Dao
public interface ActivityLocationDao {
    @Query("SELECT * FROM ActivityLocation ORDER BY timestamp DESC")
    LiveData<List<ActivityLocation>> getActivityLocations();

    @Query("SELECT * FROM ActivityLocation WHERE id = :id")
    ActivityLocation getActivityLocationById(long id);

    @Query("SELECT * FROM ActivityLocation WHERE recordId = :recordId")
    LiveData<List<ActivityLocation>> getActivityLocationsByRecordId(long recordId);

    @Insert
    void setActivityLocation(ActivityLocation location);

    @Delete
    void deleteActivityLocation(ActivityLocation location);
}

Я могу вставить, обновить и удалить ActivityRecords из MainActivity.java, но я не узнал, как я могу вставить новый ActivityLocation со ссылкой на внешний ключ в мой BroadcastReceiver, когда он получает обновленные данные о местоположении от com.google.android.gms.location.LocationResult

Итак, мой вопрос: как добавить дочерний элемент ActivityLocation со ссылкой на родительский элемент ActivityRecord и как получить экземпляр базы данных моего приложения в моем BroadcastReceiver?

1 Ответ

0 голосов
/ 14 сентября 2018

Решена проблема с AsyncTask в моем BroadcastReceiver.

Сначала мне нужно было передать контекст и список ActivityLocations в качестве параметра. Это было решено с помощью созданного частного класса params:

private static class ActivityLocationParams {
    Context context;
    List<ActivityLocation> locations;

    ActivityLocationParams(Context context, List<ActivityLocation> locations) {
        this.context = context;
        this.locations = locations;
    }
}

Затем я создал частный класс AsyncTask:

private static class addActivityLocationAsyncTask extends AsyncTask<ActivityLocationParams, Void, Integer> {
    @Override
    protected Integer doInBackground(ActivityLocationParams... params) {
        Context context = params[0].context;
        List<ActivityLocation> locations = params[0].locations;

        AppDatabase db = AppDatabase.getInstance(context);
        ActivityRecord activityRecord = db.activityRecordDao().getLastActivityRecord();

        int count = 0;
        for (ActivityLocation location : locations) {
            if (activityRecord == null) {
                continue;
            }

            ActivityLocation activityLocation
                    = new ActivityLocation(location.getLatitude(),
                    location.getLongitude(), activityRecord.getId());
            db.activityLocationDao().setActivityLocation(activityLocation);
            count += 1;
        }

        return count;
    }

    @Override
    protected void onPostExecute(Integer count) {
        Log.d(TAG, "Number of ActivityLocations added: " + count.toString());
    }
}

После завершения doInBackground я распечатал количество элементов, добавленных в базу данных для целей отладки.

Наконец, я создал объект params и вызвал AsyncTask в BroadcastReceiver:

ActivityLocationParams params = new ActivityLocationParams(context, locations);
new addActivityLocationAsyncTask().execute(params);
...