gpt4 book ai didi

android - Room 中的多态实体

转载 作者:IT王子 更新时间:2023-10-29 06:20:17 27 4
gpt4 key购买 nike

我的 Room DB 中有 3 个实体:

相册PhotosMediaItemVideosMediaItem

VideosMediaItemPhotosMediaItem 继承自 MediaItem

MediaItem 不是数据库中的实体,它只是一个抽象基类。

我想创建一个查询,以根据创建日期降序返回特定相册中的所有照片和视频媒体项。

因此查询将创建一个 MediaItems 列表,但具有派生类型。 (PhotoMediaItemVideoMediaItem)以多态方式。

这是我尝试过的:

    @Query("SELECT * FROM PhotosMediaItem WHERE PhotosMediaItem = :albumId " +
"UNION SELECT * FROM VideosMediaItem WHERE VideosMediaItem = :albumId" +
" ORDER by CreationDate DESC")
List<MediaItem> getAllMediaInAlbum(int albumId);

这显然行不通,因为它试图启动 MediaItem 对象,而这不是我的 Intent 。我希望此查询启动派生类 PhotoMediaItemVideoMediaItem

这是我的查询在迁移到 Room 之前的样子,使用常规的 SQLiteHelper,它工作得很好:

public ArrayList<MediaItem> getMediaListByAlbumId(int palbumId)
{
Cursor cursor = null;
try{
ArrayList<MediaItem> mediaList = new ArrayList<>();
String selectQuery = "SELECT "+ mPhotoId +","+ mPhotoCreationDate +", 0 AS mediaType, '' FROM "+ mPhotosTableName + " WHERE " + this.mPhotoAlbumId + "="+palbumId +
" UNION " +
"SELECT "+ mVideoId +","+ mVideoCreationDate + " ,1 AS mediaType, " + mVideoLength + " FROM " + mVideosTableName + " WHERE " + this.mVideoAlbumId +"="+palbumId +
" ORDER BY CreationDate DESC";
cursor = mDB.rawQuery(selectQuery, null);
// looping through all rows and adding to list
if (cursor.moveToFirst()){
do {
// MediaHolder consists of the media ID and its type
int mediaType = cursor.getInt(2);
MediaItem mediaItem = null;
if (mediaType == 0) {
mediaItem = new PhotoMediaItem(cursor.getInt(0), null, palbumId);
} else if (mediaType == 1) {
mediaItem = new VideoMediaItem(cursor.getInt(0), null, palbumId, cursor.getLong(3));
}
mediaList.add(mediaItem);
}
while (cursor.moveToNext());
}
return mediaList;
}
finally {
if(cursor != null){
cursor.close();
}
}

}

那我怎样才能用 Room 达到同样的效果呢?

最佳答案

我认为您在这里有多种选择:

选项 1

您使用一个表来存储所有 MediaItem s 并且您使用鉴别器列来区分视频和照片。您有一个执行查询的 DAO 方法,应用 order by并返回 Cursor .然后您可以使用现有的游标操作逻辑返回 List<MediaItem>它可能看起来像这样:

@Dao
public abstract class MediaItemDao() {

@Query("you query here")
protected Cursor getByAlbumIdInternal(int albumId);

public List<MediaItem> getByAbumId(int albumId) {
Cursor cursor = null;
try{
List<MediaItem> mediaList = new ArrayList<>();
cursor = getByAlbumIdInternal(albumId);
// looping through all rows and adding to list
if (cursor.moveToFirst()){
do {
// use the discriminator value here
int mediaType = cursor.getInt(cursor.getColumnIndex("you discriminator column name here"));
MediaItem mediaItem = null;
if (mediaType == 0) {
mediaItem = new PhotoMediaItem(cursor.getInt(0), null, palbumId);
} else if (mediaType == 1) {
mediaItem = new VideoMediaItem(cursor.getInt(0), null, palbumId, cursor.getLong(3));
}
mediaList.add(mediaItem);
} while (cursor.moveToNext());
}
return mediaList;
}
finally {
if(cursor != null){
cursor.close();
}
}
}
}

选项 2

您使用两个不同的表来存储 VideosMediaItemPhotosMediaItem .你有一个 MediaItemDao它有两个执行查询的内部方法和一个将两个结果集合并在一起并在 java 代码中应用排序的公共(public)方法。它可能看起来像这样:

@Dao
public abstract class MediaItemDao() {

@Query("your query to get the videos, no order by")
protected List<VideoMediaItem> getVideosByAlbumId(int albumId);

@Query("your query to get the photos, no order by")
protected List<PhotosMediaItem> getPhotosByAlbumId(int albumId);

@Transaction
public List<MediaItem> getByAlbumId(int albumId) {
final List<MediaItem> mediaItems = new LinkedList<>();
mediaItems.add(getVideosByAlbumId(albumId));
mediaItems.add(getPhotosByAlbumId(albumId));
Collections.sort(mediaItems, <you can add a comparator here>);
return mediaItems;
}
}

编辑:如何为此选项利用实时数据?

正如我提到的,您应该使用 LiveData作为 protected 方法的返回类型,因此您会收到有关这些表的基础更改的通知。所以它们应该是这样的:

protected LiveData<List<VideoMediaItem>> getVideosByAlbumId(int albumId);

protected LiveData<List<PhotosMediaItem>> getPhotosByAlbumId(int albumId);

为了回单LiveData对于客户端,您应该将这两种方法的输出压缩到一个流中。您可以使用自定义 MediatorLiveData 来实现此目的执行。它可能看起来像这样:

public class ZipLiveData<T1, T2, R> extends MediatorLiveData<R> {

private T1 mLastLeft;
private T2 mLastRight;
private Zipper<T1, T2, R> mZipper;

public static final <T1, T2, R> LiveData<R> create(@NonNull LiveData<T1> left, @NonNull LiveData<T2> right, Zipper<T1, T2, R> zipper) {
final ZipLiveData<T1, T2, R> liveData = new ZipLiveData(zipper);
liveData.addSource(left, value -> {
liveData.mLastLeft = value;
update();
});
liveData.addSource(right, value -> {
liveData.mLastRight = value;
update();
});
return liveData;
}

private ZipLiveData(@NonNull Zipper<T1, T2, R> zipper) {
mZipper = zipper;
}

private update() {
final R result = zipper.zip(mLastLeft, mLastRight);
setValue(result);
}

public interface Zipper<T1, T2, R> {

R zip(T1 left, T2 right);

}
}

然后您只需在您的存储库公共(public)方法中使用它,如下所示:

public List<MediaItem> getByAlbumId(int albumId) {
return ZipLiveData.create(
getVideosByAlbumId(albumId),
getPhotosByAlbumId(albumId),
(videos, photos) -> {
final List<MediaItem> mediaItems = new LinkedList<>();
mediaItems.add(videos);
mediaItems.add(photos);
Collections.sort(mediaItems, <you can add a comparator here>);
return mediaItems;
}
}

选项 3

这仅适用于您拥有存储库层的情况。

您使用两个不同的表来存储 VideosMediaItemPhotosMediaItem .每个人都有一个 DAO 类。你有一个存储库,它依赖于两个 DAO 并组合结果集,应用排序。它可能看起来像这样:

@Dao
public abstract class VideosMediaItemDao {

@Query("your query to get the videos, no order by")
public List<VideoMediaItem> getByAlbumId(int albumId);

}

@Dao
public abstract class PhotosMediaItemDao {

@Query("your query to get the photos, no order by")
public List<PhotosMediaItem> getByAlbymId(int albumId);

}

public interface MediaItemRepository {

public List<MediaItem> getByAlbumId(int albumId);

}

class MediaItemRepositoryImpl {

private final VideosMediaItemDao mVideoDao;
private final PhotosMediaItemDao mPhotoDao;

MediaItemRepositoryImpl(VideosMediaItemDao videoDao, PhotosMediaItemDao photoDao) {
mVideoDao = videoDao;
mPhotoDao = photoDao;
}

@Override
public List<MediaItem> getByAlbumId(int albumId) {
final List<MediaItem> mediaItems = new LinkedList<>();
mediaItems.add(mVideoDao.getByAlbumId(albumId));
mediaItems.add(mPhotoDao.getByAlbumId(albumId));
Collections.sort(mediaItems, <you can add a comparator here>);
return mediaItems;
}

}

关于android - Room 中的多态实体,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51972843/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com