【问题标题】:Android Room: error: setValue(T) has protected access in LiveDataAndroid Room:错误:setValue(T) 在 LiveData 中具有受保护的访问权限
【发布时间】:2026-01-20 06:35:01
【问题描述】:

我正在尝试启动并运行 Android 开发和 Room。

我正在制作一个带有播放列表和文件浏览器的音乐播放器应用程序,它能够将曲目添加到当前播放列表中。

我将播放列表保存在 Room 数据库中。

我在第一次运行程序时遇到了问题,并且数据库中没有任何数据。

我想查询数据库中最后打开的播放列表,但如果数据库中没有播放列表,我想创建一个空的 PlayList 对象。

 7    public class PlayListRepository
 8    {
 9        public PlayListRepository(Application application)
10        {
11           _application = application;
12        }
13
14        public LiveData<PlayListWithTracks> getPlayList(int playListId)
15        {
16            if (_appDao == null) {
17                InitDb();
18            }
19            LiveData<PlayListWithTracks> livePlayListWithTracks = _appDao.getByIdWithTracks(playListId);
20            if (livePlayListWithTracks.getValue() == null) {
21                livePlayListWithTracks.setValue(new PlayListWithTracks());
22            }
23            return livePlayListWithTracks;
24        }
25
26
27        private void InitDb()
28        {
29            AppDatabase db = AppDatabase.getDatabase(_application);
30            _appDao = db.appDao();
31        }
32
33        private Application _application;
34        private AppDao _appDao;
35    }

第 21 行无法编译。上面写着error: setValue(T) has protected access in LiveData

我的AppDao.getByIdWithTracks 方法如下所示:

@Dao
public interface AppDao
{
    @Transaction
    @Query("SELECT * FROM PlayList WHERE Id = :id")
    LiveData<PlayListWithTracks> getByIdWithTracks(int id);
}

我尝试将livePlayListWithTracks 转换为MutableLiveData&lt;PlayListWithTracks&gt;,但这给了我androidx.room.RoomTrackingLiveData cannot be cast to androidx.lifecycle.MutableLiveData 的运行时错误

我尝试将其转换为 RoomTrackingLiveData,但 Android Studio 无法识别 androidx.room 导入。

是我走错了路还是什么?

编辑:这是 PlayListWithTracks:

public class PlayListWithTracks
{
    @Embedded
    public PlayList playList;
    @Relation(
            parentColumn = "id",
            entityColumn = "playListId"
    )
    public List<Track> tracks = new Vector<Track>();
}

【问题讨论】:

  • 显示 livePlayListWithTracks.setValue 这个方法。请发布 viewModel 类代码
  • 视图模型只是调用了上面不会编译的getPlayList() 方法。如果有帮助,我发布了PlayListWithTracks
  • 一般来说,如果你不创建LiveData,你不能修改LiveData。在这种情况下,您没有创建 LiveData -- Room 是创建的。您使用的是 Java,而不是 Kotlin,这限制了您的选择。同样,您使用的是 Room 中的 LiveData,而不是 RxJava,这限制了您的选择。也许您可以使用Transformations.map()(例如,在您的视图模型中)来处理这种“提供默认结果”的场景。
  • @MattGregory:“我认为修改数据是 LiveData 的用途”——是的,对于LiveData创建者,而不是消费者我>。在这种情况下,您只是消费者。 “一旦从数据库中获取 LiveData 类,我是否应该删除它?” - 通常不会,因为这将是您了解数据库更改的方式。但是,这取决于场景。 “然后将有效负载包装在 MutableLiveData 中,因为我需要它来监控用户所做的更改?” -- 通常,您会将用户更改存储在数据库本身中。但是,同样,这取决于场景。
  • @MattGregory:您可以创建LiveData 的子类,或使用MutableLiveData,或使用MediatorLiveData,既是LiveData 的创建者又(可能)是消费者。但是,如果您从其他人(例如 Room 或其他图书馆)获得LiveData,那么您只是消费者。

标签: java android android-room


【解决方案1】:

LiveData 代表数据库中的数据。如果您从应用程序的任何其他部分修改数据库中的该条目,您的LiveData 将反映该更改。尝试为LiveData 设置另一个值是没有用的。

如果您不需要观察数据的变化,那么您可以在数据访问对象中返回对象。像这样:

@Dao
public interface AppDao
{
    @Transaction
    @Query("SELECT * FROM PlayList WHERE Id = :id")
    PlayListWithTracks getByIdWithTracks(int id);
}

也许更好的方法是在数据库中创建一个新的播放列表条目,如果它不存在,然后访问该条目。这意味着您可以使用函数中收到的id 将新的PlayListWithTracks 实体添加到数据库中,然后访问该实体

【讨论】:

  • 好的,这开始有意义了。我将尝试在数据库中插入一条记录。谢谢!
最近更新 更多