Сравнение и / или обновление репозитория базы данных в Android Kotlin?

#android #database #kotlin #repository-pattern #android-livedata

#Android #База данных #kotlin #репозиторий-шаблон #android-livedata

Вопрос:

Я новичок в программировании на Android и хочу попробовать изучить лучшие практики. Мое первое приложение, которое я создаю, — это приложение для подкастов для отображения подкастов из rss-канала и их воспроизведения. То, что у меня есть до сих пор, работает, но я знаю, что могу заставить его работать лучше.

Я использую базу данных Room с шаблоном репозитория, что может быть излишним, потому что мне, вероятно, не нужно сохранять список подкастов при смерти приложения, если я просто собираюсь повторно проанализировать канал при запуске. В моем классе репозитория я вызываю свой класс FetchRSS для выполнения сетевого вызова в init{ } блоке, который возвращает a List<Podcast> .

Я знаю, что я что-то не так делаю.

В моем PodcastDao я должен использовать @Insert(onConflict = OnConflictStrategy.REPLACE) , потому что база данных уже существует, и я получаю ошибку SQL 1555 относительно повторяющихся идентификаторов первичного ключа. По логике вещей, было бы лучше проверить, есть ли добавляемая запись уже в базе данных, но я не уверен, как это сделать. Или, что нелогично, очистить базу данных при смерти приложения, но тогда зачем вообще беспокоиться о базе данных. В идеале я хотел бы иметь функцию обновления (даже если RSS обновляется не чаще двух раз в неделю), но я не уверен, как лучше это сделать.

Если у кого-нибудь есть какие-либо мысли об улучшении этого или хорошая книга для изучения Android, я был бы внимателен. Большое спасибо всем, кто нашел время, чтобы посмотреть на это!

PodcastDao.kt

 @Dao
interface PodcastDao {

    @Query("SELECT * FROM podcast")  // get everything from the database
    fun getPodcasts(): LiveData<List<Podcast>>

    @Query("SELECT * FROM podcast WHERE id=(:id)") // get the specific podcast
    fun getPodcast(id: String): LiveData<Podcast?>

//    @Insert(onConflict = OnConflictStrategy.REPLACE)
//    fun addPodcasts(podcasts: LiveData<List<Podcast>>)
//    this causes a build error with the generated PodcastDao.java file
// logcat error: Type of the parameter must be a class annotated with @Entity or a collection/array of it.

    @Insert(onConflict = OnConflictStrategy.REPLACE)
    fun addPodcast(podcast: Podcast)
}
 

PodcastRepository.kt

 class PodcastRepository private constructor(context: Context) {

private lateinit var podcasts: List<Podcast>

    init {

        CoroutineScope(Dispatchers.Main).launch {

            podcasts = FetchRSS().fetchRss() // executes on Dispatchers.IO and returns parsed rss List<Podcast>

            // this seems silly to add them one at a time, especially since the list is rather large
            for (pod in podcasts) {
                addPodcast(pod)
            }
            //it seems a better choice to dump the full list into the database at once
            //however I can't figure out how to put the List<Podcast> into a LiveData<List<Podcast>> object
            //or maybe I'm misunderstanding something about LiveData<>
            //addPodcasts(podcasts)
        }
    }

    suspend fun addPodcast(podcast: Podcast){
        withContext(Dispatchers.IO){
            podcastDao.addPodcast(podcast)
        }

// this needs to receive the LiveData<List<Podcast>>, or a List<Podcast> and cram it into LiveData<>?
//    suspend fun addPodcasts(podcasts: LiveData<List<Podcast>>) {
//        withContext(Dispatchers.IO){
//            podcastDao.addPodcasts(podcasts)
//        }
//    }
    }
 

Ответ №1:

 fun addPodcasts(podcasts: LiveData<List<Podcast>>)
 

должно быть

 fun addPodcasts(podcasts: <List<Podcast>>)
 

Итак, теперь вы можете вызывать podcastDao.addPodcasts(podcasts) (where podcasts имеет тип List<Podcast>> ) из своего репозитория вместо того, чтобы вставлять их один за другим через цикл for .

Вы не можете вставить LiveData в Room, только объекты, помеченные @Entity . Однако запрос может возвращать LiveData со списком этих объектов. Вы также можете вернуть только список.

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

1. Сработало как шарм. На всякий случай я удалил свою базу данных и воссоздал ее с помощью addPodcasts(podcasts)