Android Room: 错误: setValue(T)的访问受保护,无法在LiveData中使用

huangapple go评论57阅读模式
英文:

Android Room: error: setValue(T) has protected access in LiveData

问题

我正在尝试开始进行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)在LiveData中具有受保护的访问权限`。

我的`AppDao.getByIdWithTracks`方法如下

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

我尝试将`livePlayListWithTracks`强制转换为`MutableLiveData<PlayListWithTracks>`,但这会导致运行时错误`androidx.room.RoomTrackingLiveData无法转换为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>();
}
英文:

I'm trying to get up and running with Android development and Room.

I'm making a music player app with playlists and a file browser that will be able to add tracks to the current playlist.

I'm saving the playlists in a Room database.

I'm running into the problem of running the program from the first time, and there not being any data in the database.

I want to query the database for the last playlist opened, but if there are no playlists in the database, I want to create an empty PlayList object.

 7    public class PlayListRepository
8    {
9        public PlayListRepository(Application application)
10        {
11           _application = application;
12        }
13
14        public LiveData&lt;PlayListWithTracks&gt; getPlayList(int playListId)
15        {
16            if (_appDao == null) {
17                InitDb();
18            }
19            LiveData&lt;PlayListWithTracks&gt; 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    }

Line 21 doesn't compile. It says error: setValue(T) has protected access in LiveData.

My AppDao.getByIdWithTracks method looks like this:

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

I've tried casting livePlayListWithTracks to MutableLiveData&lt;PlayListWithTracks&gt;, but that gives me a runtime error of androidx.room.RoomTrackingLiveData cannot be cast to androidx.lifecycle.MutableLiveData

I've tried casting it to RoomTrackingLiveData, but Android Studio doesn't recognize the androidx.room import.

Am I on the wrong track or what?

Edit: Here is PlayListWithTracks:

public class PlayListWithTracks
{
@Embedded
public PlayList playList;
@Relation(
parentColumn = &quot;id&quot;,
entityColumn = &quot;playListId&quot;
)
public List&lt;Track&gt; tracks = new Vector&lt;Track&gt;();
}

答案1

得分: 2

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

如果您不需要观察数据的更改,那么您可能可以在数据访问对象中直接返回对象。就像这样:

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

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

英文:

LiveData represents the data in your database. If you modify that entry in the database from any other part of your application your LiveData will reflect that change. It serves no purpose to try and set another value to the LiveData.

If you do not require to observe changes in the Data then you can probably return the object in the Data Access Object. Like so:

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

Perhaps the better approach would be to create a new playlist entry in the database if it does not exist and then access that entry. Meaning that you could add a new PlayListWithTracks entity to the database with the id received in the function and then access that entity

huangapple
  • 本文由 发表于 2020年9月20日 00:02:05
  • 转载请务必保留本文链接:https://go.coder-hub.com/63970736.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定