#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
, чтобы быть как создателем, так и (возможно) потребителем aLiveData
. Но если вы получаете aLiveData
от кого-то другого (например, от Room или другой библиотеки), вы просто потребитель.
Ответ №1:
LiveData
представляет данные в вашей базе данных. Если вы измените эту запись в базе данных из любой другой части вашего приложения LiveData
, вы отразите это изменение. Бесполезно пытаться установить другое значение для LiveData
.
Если вам не требуется отслеживать изменения в данных, вы, вероятно, можете вернуть объект в объект доступа к данным. Вот так:
@Dao
public interface AppDao
{
@Transaction
@Query("SELECT * FROM PlayList WHERE Id = :id")
PlayListWithTracks getByIdWithTracks(int id);
}
Возможно, лучшим подходом было бы создать новую запись списка воспроизведения в базе данных, если она не существует, а затем получить доступ к этой записи. Это означает, что вы можете добавить новый PlayListWithTracks
объект в базу данных с id
полученным в функции, а затем получить доступ к этому объекту
Комментарии:
1. Хорошо, это начинает иметь смысл. Я попробую вставить запись в базу данных. Спасибо!