如何将项目添加到具有Android Room中父实体的外键引用的子实体?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何将项目添加到具有Android Room中父实体的外键引用的子实体?相关的知识,希望对你有一定的参考价值。

我正在尝试编写一个类似于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中获取我的应用程序数据库的实例?

答案

解决了我的BroadcastReceiver中的AsyncTask问题。

我首先需要将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对象并在BroadcastReceiver中调用了AsyncTask:

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

以上是关于如何将项目添加到具有Android Room中父实体的外键引用的子实体?的主要内容,如果未能解决你的问题,请参考以下文章

Android:如何使 Kotlin 中所有对象列表的类型转换器(用于 Room)通用

TypeConverter() 在 Android 中的 Room 出现 TypeConverter 错误时具有私有访问权限

仅具有本地 Room 数据库的 Android Paging v3:如何滚动到分页列表中的特定位置?

如何将 Not Null 表列迁移到 Android Room 数据库中的 Null

如何将带有 Android Room 的应用添加为使用 makefile 编译的系统应用?

GeoPoint 不允许存储在 Room 中