From a987d817b5f4571e46cd2565f1b0922bc5fd438a Mon Sep 17 00:00:00 2001 From: DJYohann Date: Sun, 12 Feb 2023 12:10:17 +0100 Subject: [PATCH] add repo and vm --- .idea/deploymentTargetDropDown.xml | 4 +- app/build.gradle | 22 ++++---- .../allomovies/AlloMoviesApplication.kt | 11 ++++ .../yobreuil/allomovies/api/GenreManager.kt | 23 ++++++++ .../yobreuil/allomovies/api/GenreService.kt | 10 ++++ .../allomovies/data/entities/Genre.kt | 7 ++- .../data/entities/GenreMovieCrossRef.kt | 9 ++++ .../data/entities/GenreWithMovies.kt | 15 ++++++ .../allomovies/data/entities/Movie.kt | 7 ++- .../data/entities/MovieWithGenres.kt | 15 ++++++ .../data/persistance/AlloMoviesDatabase.kt | 24 ++++++--- .../allomovies/data/persistance/GenreDao.kt | 11 ---- .../allomovies/data/persistance/MovieDao.kt | 10 ---- .../data/persistance/dao/GenreDao.kt | 33 ++++++++++++ .../data/persistance/dao/MovieDao.kt | 19 +++++++ .../data/repositories/GenreRepository.kt | 24 +++++++++ .../data/repositories/MovieRepository.kt | 4 ++ .../ui/fragment/GenreListFragment.kt | 6 +-- .../allomovies/ui/viewmodel/GenreViewModel.kt | 11 ++++ app/src/main/res/layout/card_genre.xml | 52 +++++++++++-------- .../main/res/layout/fragment_genre_list.xml | 36 +++++++------ build.gradle | 4 +- 22 files changed, 271 insertions(+), 86 deletions(-) create mode 100644 app/src/main/java/fr/yobreuil/allomovies/AlloMoviesApplication.kt create mode 100644 app/src/main/java/fr/yobreuil/allomovies/api/GenreManager.kt create mode 100644 app/src/main/java/fr/yobreuil/allomovies/api/GenreService.kt create mode 100644 app/src/main/java/fr/yobreuil/allomovies/data/entities/GenreMovieCrossRef.kt create mode 100644 app/src/main/java/fr/yobreuil/allomovies/data/entities/GenreWithMovies.kt create mode 100644 app/src/main/java/fr/yobreuil/allomovies/data/entities/MovieWithGenres.kt delete mode 100644 app/src/main/java/fr/yobreuil/allomovies/data/persistance/GenreDao.kt delete mode 100644 app/src/main/java/fr/yobreuil/allomovies/data/persistance/MovieDao.kt create mode 100644 app/src/main/java/fr/yobreuil/allomovies/data/persistance/dao/GenreDao.kt create mode 100644 app/src/main/java/fr/yobreuil/allomovies/data/persistance/dao/MovieDao.kt create mode 100644 app/src/main/java/fr/yobreuil/allomovies/data/repositories/GenreRepository.kt create mode 100644 app/src/main/java/fr/yobreuil/allomovies/data/repositories/MovieRepository.kt create mode 100644 app/src/main/java/fr/yobreuil/allomovies/ui/viewmodel/GenreViewModel.kt diff --git a/.idea/deploymentTargetDropDown.xml b/.idea/deploymentTargetDropDown.xml index 128c8ea..5ab08f1 100644 --- a/.idea/deploymentTargetDropDown.xml +++ b/.idea/deploymentTargetDropDown.xml @@ -7,11 +7,11 @@ - + - + \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index d00162c..9e75609 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -5,12 +5,12 @@ plugins { android { namespace 'fr.yobreuil.allomovies' - compileSdk 32 + compileSdk 33 defaultConfig { applicationId "fr.yobreuil.allomovies" minSdk 16 - targetSdk 32 + targetSdk 33 versionCode 1 versionName "1.0" @@ -30,16 +30,20 @@ android { kotlinOptions { jvmTarget = '1.8' } + buildFeatures { + dataBinding true + } } dependencies { - - implementation 'androidx.core:core-ktx:1.7.0' - implementation 'androidx.appcompat:appcompat:1.5.1' - implementation 'com.google.android.material:material:1.7.0' - implementation 'androidx.room:room-common:2.4.2' - implementation 'androidx.constraintlayout:constraintlayout:2.1.3' - implementation 'androidx.room:room-ktx:2.4.2' + implementation 'androidx.core:core-ktx:1.9.0' + implementation 'androidx.appcompat:appcompat:1.6.0' + implementation 'com.google.android.material:material:1.8.0' + implementation 'androidx.room:room-common:2.5.0' + implementation 'androidx.constraintlayout:constraintlayout:2.1.4' + implementation 'androidx.room:room-ktx:2.5.0' + implementation 'com.squareup.retrofit2:retrofit:2.9.0' + implementation 'com.squareup.retrofit2:converter-gson:2.9.0' testImplementation 'junit:junit:4.13.2' androidTestImplementation 'androidx.test.ext:junit:1.1.5' androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1' diff --git a/app/src/main/java/fr/yobreuil/allomovies/AlloMoviesApplication.kt b/app/src/main/java/fr/yobreuil/allomovies/AlloMoviesApplication.kt new file mode 100644 index 0000000..62b50a3 --- /dev/null +++ b/app/src/main/java/fr/yobreuil/allomovies/AlloMoviesApplication.kt @@ -0,0 +1,11 @@ +package fr.yobreuil.allomovies + +import android.app.Application +import fr.yobreuil.allomovies.data.persistance.AlloMoviesDatabase + +class AlloMoviesApplication : Application() { + override fun onCreate() { + super.onCreate() + AlloMoviesDatabase.initialize(this) + } +} \ No newline at end of file diff --git a/app/src/main/java/fr/yobreuil/allomovies/api/GenreManager.kt b/app/src/main/java/fr/yobreuil/allomovies/api/GenreManager.kt new file mode 100644 index 0000000..6cabb37 --- /dev/null +++ b/app/src/main/java/fr/yobreuil/allomovies/api/GenreManager.kt @@ -0,0 +1,23 @@ +package fr.yobreuil.allomovies.api + +import fr.yobreuil.allomovies.data.entities.Genre +import retrofit2.Call +import retrofit2.Retrofit +import retrofit2.converter.gson.GsonConverterFactory + +class GenreManager { + private val URL = "https://api.themoviedb.org/3/genre/movie/list?api_key=3fda2cd4981d6b7ee72244a2cdd869a3&language=fr-FR" + + fun getAllGenres() : Call> { + val retrofit = Retrofit.Builder() + .baseUrl(URL) + .addConverterFactory(GsonConverterFactory.create()) + .build() + + val service = retrofit.create(GenreService::class.java) + + return service.getGenres() + } + + +} \ No newline at end of file diff --git a/app/src/main/java/fr/yobreuil/allomovies/api/GenreService.kt b/app/src/main/java/fr/yobreuil/allomovies/api/GenreService.kt new file mode 100644 index 0000000..bde4d35 --- /dev/null +++ b/app/src/main/java/fr/yobreuil/allomovies/api/GenreService.kt @@ -0,0 +1,10 @@ +package fr.yobreuil.allomovies.api + +import fr.yobreuil.allomovies.data.entities.Genre +import retrofit2.Call +import retrofit2.http.GET + +interface GenreService { + @GET("genre") + fun getGenres() : Call> +} \ No newline at end of file diff --git a/app/src/main/java/fr/yobreuil/allomovies/data/entities/Genre.kt b/app/src/main/java/fr/yobreuil/allomovies/data/entities/Genre.kt index 07606a6..1f16977 100644 --- a/app/src/main/java/fr/yobreuil/allomovies/data/entities/Genre.kt +++ b/app/src/main/java/fr/yobreuil/allomovies/data/entities/Genre.kt @@ -6,5 +6,8 @@ import androidx.room.PrimaryKey const val GENRE_DEFAULT_ID = 0L @Entity(tableName = "genres") -data class Genre(var name: String = "", - @PrimaryKey(autoGenerate = true) val id: Long = GENRE_DEFAULT_ID) +data class Genre( + @PrimaryKey(autoGenerate = true) + val genreId: Long = GENRE_DEFAULT_ID, + var genreName: String = "" +) \ No newline at end of file diff --git a/app/src/main/java/fr/yobreuil/allomovies/data/entities/GenreMovieCrossRef.kt b/app/src/main/java/fr/yobreuil/allomovies/data/entities/GenreMovieCrossRef.kt new file mode 100644 index 0000000..1cd9f89 --- /dev/null +++ b/app/src/main/java/fr/yobreuil/allomovies/data/entities/GenreMovieCrossRef.kt @@ -0,0 +1,9 @@ +package fr.yobreuil.allomovies.data.entities + +import androidx.room.Entity + +@Entity(primaryKeys = ["genreId", "movieId"]) +data class GenreMovieCrossRef( + val genreId: Long, + val movieId: Long +) diff --git a/app/src/main/java/fr/yobreuil/allomovies/data/entities/GenreWithMovies.kt b/app/src/main/java/fr/yobreuil/allomovies/data/entities/GenreWithMovies.kt new file mode 100644 index 0000000..a4e64d4 --- /dev/null +++ b/app/src/main/java/fr/yobreuil/allomovies/data/entities/GenreWithMovies.kt @@ -0,0 +1,15 @@ +package fr.yobreuil.allomovies.data.entities + +import androidx.room.Embedded +import androidx.room.Junction +import androidx.room.Relation + +data class GenreWithMovies( + @Embedded val genre: Genre, + @Relation( + parentColumn = "genreId", + entityColumn = "movieId", + associateBy = Junction(GenreMovieCrossRef::class) + ) + val movies : List +) \ No newline at end of file diff --git a/app/src/main/java/fr/yobreuil/allomovies/data/entities/Movie.kt b/app/src/main/java/fr/yobreuil/allomovies/data/entities/Movie.kt index 8ca9fdb..6ff2120 100644 --- a/app/src/main/java/fr/yobreuil/allomovies/data/entities/Movie.kt +++ b/app/src/main/java/fr/yobreuil/allomovies/data/entities/Movie.kt @@ -6,5 +6,8 @@ import androidx.room.PrimaryKey const val MOVIE_DEFAULT_ID = 0L @Entity(tableName = "movies") -data class Movie(var name: String = "", - @PrimaryKey(autoGenerate = true) val id: Long = MOVIE_DEFAULT_ID) +data class Movie( + @PrimaryKey(autoGenerate = true) + val movieId: Long = MOVIE_DEFAULT_ID, + val movieName: String = "" +) \ No newline at end of file diff --git a/app/src/main/java/fr/yobreuil/allomovies/data/entities/MovieWithGenres.kt b/app/src/main/java/fr/yobreuil/allomovies/data/entities/MovieWithGenres.kt new file mode 100644 index 0000000..cb68387 --- /dev/null +++ b/app/src/main/java/fr/yobreuil/allomovies/data/entities/MovieWithGenres.kt @@ -0,0 +1,15 @@ +package fr.yobreuil.allomovies.data.entities + +import androidx.room.Embedded +import androidx.room.Junction +import androidx.room.Relation + +data class MovieWithGenres( + @Embedded val movie: Movie, + @Relation( + parentColumn = "movieId", + entityColumn = "genreId", + associateBy = Junction(GenreMovieCrossRef::class) + ) + val genres : List +) \ No newline at end of file diff --git a/app/src/main/java/fr/yobreuil/allomovies/data/persistance/AlloMoviesDatabase.kt b/app/src/main/java/fr/yobreuil/allomovies/data/persistance/AlloMoviesDatabase.kt index 1cac5d3..47d88bc 100644 --- a/app/src/main/java/fr/yobreuil/allomovies/data/persistance/AlloMoviesDatabase.kt +++ b/app/src/main/java/fr/yobreuil/allomovies/data/persistance/AlloMoviesDatabase.kt @@ -4,14 +4,18 @@ import android.app.Application import androidx.room.Database import androidx.room.Room import androidx.room.RoomDatabase -import fr.yobreuil.allomovies.data.Genre -import fr.yobreuil.allomovies.data.Movie +import fr.yobreuil.allomovies.AlloMoviesApplication +import fr.yobreuil.allomovies.data.entities.Genre +import fr.yobreuil.allomovies.data.entities.Movie +import fr.yobreuil.allomovies.data.persistance.dao.GenreDao +import fr.yobreuil.allomovies.data.persistance.dao.MovieDao private const val ALLO_MOVIES_DB_FILENAME = "allomovies.db" @Database(entities = [Genre::class, Movie::class], version = 1, exportSchema = false) abstract class AlloMoviesDatabase : RoomDatabase() { abstract fun genreDao(): GenreDao + abstract fun movieDao(): MovieDao companion object { private lateinit var application: Application @@ -19,7 +23,7 @@ abstract class AlloMoviesDatabase : RoomDatabase() { @Volatile private var INSTANCE: AlloMoviesDatabase? = null - /*fun getInstance(): AlloMoviesDatabase { + fun getInstance() : AlloMoviesDatabase { if (::application.isInitialized) { if (INSTANCE == null) { synchronized(this) { @@ -29,13 +33,21 @@ abstract class AlloMoviesDatabase : RoomDatabase() { AlloMoviesDatabase::class.java, ALLO_MOVIES_DB_FILENAME ).build() - - INSTANCE?.genreDao() } } } return INSTANCE!! } - }*/ + else { + throw RuntimeException("Database must be first initialized") + } + } + + @Synchronized + fun initialize(app: AlloMoviesApplication) { + if (::application.isInitialized) + throw RuntimeException("Database must not be initialized twice") + application = app + } } } \ No newline at end of file diff --git a/app/src/main/java/fr/yobreuil/allomovies/data/persistance/GenreDao.kt b/app/src/main/java/fr/yobreuil/allomovies/data/persistance/GenreDao.kt deleted file mode 100644 index 37de020..0000000 --- a/app/src/main/java/fr/yobreuil/allomovies/data/persistance/GenreDao.kt +++ /dev/null @@ -1,11 +0,0 @@ -package fr.yobreuil.allomovies.data.persistance - -import androidx.room.Dao -import androidx.room.Query -import fr.yobreuil.allomovies.data.Genre - -@Dao -interface GenreDao { - @Query("SELECT * FROM genres") - fun getAll(): List -} \ No newline at end of file diff --git a/app/src/main/java/fr/yobreuil/allomovies/data/persistance/MovieDao.kt b/app/src/main/java/fr/yobreuil/allomovies/data/persistance/MovieDao.kt deleted file mode 100644 index dd27ba4..0000000 --- a/app/src/main/java/fr/yobreuil/allomovies/data/persistance/MovieDao.kt +++ /dev/null @@ -1,10 +0,0 @@ -package fr.yobreuil.allomovies.data.persistance - -import androidx.room.Dao -import androidx.room.Query - -@Dao -interface MovieDao { - @Query("") - fun getAll(); -} \ No newline at end of file diff --git a/app/src/main/java/fr/yobreuil/allomovies/data/persistance/dao/GenreDao.kt b/app/src/main/java/fr/yobreuil/allomovies/data/persistance/dao/GenreDao.kt new file mode 100644 index 0000000..6876c83 --- /dev/null +++ b/app/src/main/java/fr/yobreuil/allomovies/data/persistance/dao/GenreDao.kt @@ -0,0 +1,33 @@ +package fr.yobreuil.allomovies.data.persistance.dao + +import androidx.lifecycle.LiveData +import androidx.room.* +import fr.yobreuil.allomovies.data.entities.Genre +import fr.yobreuil.allomovies.data.entities.GenreWithMovies + +@Dao +interface GenreDao { + @Query("SELECT * FROM genres") + fun getAll() : LiveData> + + @Query("SELECT * FROM genres WHERE id = :id") + fun getById(id : Long) : LiveData + + @Query("SELECT") + fun getGenreWithMovies(idGenre : Long) + + @Query("SELECT") + fun getMoviesByGenre(genreId: Long): LiveData + + @Insert(onConflict = OnConflictStrategy.REPLACE) + suspend fun insert(genre: Genre) + + @Insert + suspend fun insertAll(vararg genres: Genre) + + @Update(onConflict = OnConflictStrategy.REPLACE) + suspend fun update(genre: Genre) + + @Delete + suspend fun delete(genre: Genre) +} \ No newline at end of file diff --git a/app/src/main/java/fr/yobreuil/allomovies/data/persistance/dao/MovieDao.kt b/app/src/main/java/fr/yobreuil/allomovies/data/persistance/dao/MovieDao.kt new file mode 100644 index 0000000..fbadc3c --- /dev/null +++ b/app/src/main/java/fr/yobreuil/allomovies/data/persistance/dao/MovieDao.kt @@ -0,0 +1,19 @@ +package fr.yobreuil.allomovies.data.persistance.dao + +import androidx.lifecycle.LiveData +import androidx.room.Dao +import androidx.room.Query +import fr.yobreuil.allomovies.data.entities.GenreWithMovies +import fr.yobreuil.allomovies.data.entities.Movie + +@Dao +interface MovieDao { + @Query("SELECT * FROM movies") + fun getAll() : LiveData> + + @Query("SELECT * FROM movies ORDER BY movieName ASC") + fun getAllAlphabetical() : LiveData> + + @Query("SELECT * FROM movies ORDER BY movieName ASC") + fun getMoviesByGenre(genreId: Long) : LiveData; +} \ No newline at end of file diff --git a/app/src/main/java/fr/yobreuil/allomovies/data/repositories/GenreRepository.kt b/app/src/main/java/fr/yobreuil/allomovies/data/repositories/GenreRepository.kt new file mode 100644 index 0000000..4f2c3ff --- /dev/null +++ b/app/src/main/java/fr/yobreuil/allomovies/data/repositories/GenreRepository.kt @@ -0,0 +1,24 @@ +package fr.yobreuil.allomovies.data.repositories + +import android.util.Log +import androidx.lifecycle.LiveData +import fr.yobreuil.allomovies.data.entities.Genre +import fr.yobreuil.allomovies.data.persistance.dao.GenreDao +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.withContext + +class GenreRepository(private val genreDao: GenreDao) { + suspend fun insert(genre: Genre) = withContext(Dispatchers.IO) { Log.i("GenreRepo", "INSERT"); genreDao.insert(genre) } + suspend fun delete(genre: Genre) = withContext(Dispatchers.IO) { Log.i("GenreRepo", "DELETE"); genreDao.delete(genre) } + suspend fun update(genre: Genre) = withContext(Dispatchers.IO) { Log.i("GenreRepo", "UPDATE"); genreDao.update(genre) } + + fun findById(genreId: Long): LiveData { + Log.i("GenreRepo", "FIND GENRE") + return genreDao.getById(genreId) + } + + fun getAll(): LiveData> { + Log.i("GenreRepo", "GET ALL GENRES") + return genreDao.getAll() + } +} \ No newline at end of file diff --git a/app/src/main/java/fr/yobreuil/allomovies/data/repositories/MovieRepository.kt b/app/src/main/java/fr/yobreuil/allomovies/data/repositories/MovieRepository.kt new file mode 100644 index 0000000..915149d --- /dev/null +++ b/app/src/main/java/fr/yobreuil/allomovies/data/repositories/MovieRepository.kt @@ -0,0 +1,4 @@ +package fr.yobreuil.allomovies.data.repositories + +class MovieRepository { +} \ No newline at end of file diff --git a/app/src/main/java/fr/yobreuil/allomovies/ui/fragment/GenreListFragment.kt b/app/src/main/java/fr/yobreuil/allomovies/ui/fragment/GenreListFragment.kt index 86c8006..b27a94b 100644 --- a/app/src/main/java/fr/yobreuil/allomovies/ui/fragment/GenreListFragment.kt +++ b/app/src/main/java/fr/yobreuil/allomovies/ui/fragment/GenreListFragment.kt @@ -7,11 +7,7 @@ import android.view.View import android.view.ViewGroup import fr.yobreuil.allomovies.R -/** - * A simple [Fragment] subclass. - * Use the [GenreListFragment.newInstance] factory method to - * create an instance of this fragment. - */ + class GenreListFragment : Fragment() { override fun onCreate(savedInstanceState: Bundle?) { diff --git a/app/src/main/java/fr/yobreuil/allomovies/ui/viewmodel/GenreViewModel.kt b/app/src/main/java/fr/yobreuil/allomovies/ui/viewmodel/GenreViewModel.kt new file mode 100644 index 0000000..a8797e8 --- /dev/null +++ b/app/src/main/java/fr/yobreuil/allomovies/ui/viewmodel/GenreViewModel.kt @@ -0,0 +1,11 @@ +package fr.yobreuil.allomovies.ui.viewmodel + +import androidx.lifecycle.ViewModel +import fr.yobreuil.allomovies.data.persistance.AlloMoviesDatabase +import fr.yobreuil.allomovies.data.repositories.GenreRepository + +class GenreViewModel : ViewModel() { + private val genreRepo = GenreRepository(AlloMoviesDatabase.getInstance().genreDao()) + + val genreList = genreRepo.getAll() +} \ No newline at end of file diff --git a/app/src/main/res/layout/card_genre.xml b/app/src/main/res/layout/card_genre.xml index 3c84cf0..52af29c 100644 --- a/app/src/main/res/layout/card_genre.xml +++ b/app/src/main/res/layout/card_genre.xml @@ -1,28 +1,38 @@ - + xmlns:tools="http://schemas.android.com/tools"> + + + - + - + android:gravity="center_horizontal" + android:orientation="vertical"> + + + + + + + - - - \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_genre_list.xml b/app/src/main/res/layout/fragment_genre_list.xml index 154f0ec..3da8a7e 100644 --- a/app/src/main/res/layout/fragment_genre_list.xml +++ b/app/src/main/res/layout/fragment_genre_list.xml @@ -1,23 +1,27 @@ - + xmlns:tools="http://schemas.android.com/tools"> - + + + + - + - + + - \ No newline at end of file + + diff --git a/build.gradle b/build.gradle index 3aa8eea..b2ebb1e 100644 --- a/build.gradle +++ b/build.gradle @@ -1,6 +1,6 @@ // Top-level build file where you can add configuration options common to all sub-projects/modules. plugins { - id 'com.android.application' version '7.4.0' apply false - id 'com.android.library' version '7.4.0' apply false + id 'com.android.application' version '7.4.1' apply false + id 'com.android.library' version '7.4.1' apply false id 'org.jetbrains.kotlin.android' version '1.7.20' apply false } \ No newline at end of file