Комната Android: ошибка: setValue (T) имеет защищенный доступ в LiveData

#java #android #android-room

#java #Android #android-комната

Вопрос:

Я пытаюсь начать и запустить разработку Android и Room.

Я создаю приложение для музыкального проигрывателя с плейлистами и файловым браузером, которое сможет добавлять треки в текущий плейлист.

Я сохраняю плейлисты в базе данных комнат.

Я сталкиваюсь с проблемой запуска программы с первого раза, и в базе данных нет никаких данных.

Я хочу запросить базу данных для последнего открытого списка воспроизведения, но если в базе данных нет списков воспроизведения, я хочу создать пустой объект списка воспроизведения.

  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<PlayListWithTracks> , но это выдает ошибку времени выполнения androidx.room.RoomTrackingLiveData cannot be cast to androidx.lifecycle.MutableLiveData

Я пытался применить его к RoomTrackingLiveData , но Android Studio не распознает androidx.room импорт.

Я на неверном пути или что?

Редактировать: вот список воспроизведения с дорожками:

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

Комментарии:

1. показать livePlayListWithTracks.setValue этот метод. Пожалуйста, опубликуйте код класса ViewModel

2. Модель представления просто вызывает getPlayList() метод, который не будет компилироваться выше. Я опубликовал PlayListWithTracks , если это поможет.

3. В общем, если вы не создаете LiveData , вы не можете изменить LiveData . В этом случае вы не создали LiveData — Room did . Вы используете Java, а не Kotlin, что ограничивает ваши возможности. Аналогично, вы используете LiveData from Room, а не RxJava, что ограничивает ваши возможности. Вероятно, вы можете использовать Transformations.map() (например, в своей viewmodel) для обработки этого сценария «предоставления результатов по умолчанию».

4. @MattGregory: «Я думал, что для изменения данных предназначены LiveData» — да, для создателя LiveData , а не для потребителя . В этом случае вы являетесь только потребителем. «Должен ли я просто избавиться от класса LiveData, как только я получу его из базы данных?» — обычно нет, поскольку именно так вы узнаете об изменениях в базе данных. Но это зависит от сценария. «А затем оберните полезную нагрузку в изменяемые LiveData, потому что мне это нужно для отслеживания изменений, внесенных пользователем?» — как правило, вы сохраняете пользовательские изменения в самой базе данных. Но, опять же, это зависит от сценария.

5. @MattGregory: вы можете создавать подклассы LiveData , или использовать MutableLiveData , или использовать MediatorLiveData , чтобы быть как создателем, так и (возможно) потребителем a LiveData . Но если вы получаете a LiveData от кого-то другого (например, от Room или другой библиотеки), вы просто потребитель.

Ответ №1:

LiveData представляет данные в вашей базе данных. Если вы измените эту запись в базе данных из любой другой части вашего приложения LiveData , вы отразите это изменение. Бесполезно пытаться установить другое значение для LiveData .

Если вам не требуется отслеживать изменения в данных, вы, вероятно, можете вернуть объект в объект доступа к данным. Вот так:

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

Возможно, лучшим подходом было бы создать новую запись списка воспроизведения в базе данных, если она не существует, а затем получить доступ к этой записи. Это означает, что вы можете добавить новый PlayListWithTracks объект в базу данных с id полученным в функции, а затем получить доступ к этому объекту

Комментарии:

1. Хорошо, это начинает иметь смысл. Я попробую вставить запись в базу данных. Спасибо!