add repo and vm

main
DJYohann 2 years ago
parent c9ca71b7a0
commit a987d817b5

@ -7,11 +7,11 @@
<deviceKey>
<Key>
<type value="VIRTUAL_DEVICE_PATH" />
<value value="$USER_HOME$/.android/avd/Pixel_4_API_16.avd" />
<value value="$USER_HOME$/.android/avd/Pixel_6_API_22.avd" />
</Key>
</deviceKey>
</Target>
</targetSelectedWithDropDown>
<timeTargetWasSelectedWithDropDown value="2023-01-23T13:44:28.832263Z" />
<timeTargetWasSelectedWithDropDown value="2023-01-30T15:00:02.892590Z" />
</component>
</project>

@ -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'

@ -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)
}
}

@ -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<List<Genre>> {
val retrofit = Retrofit.Builder()
.baseUrl(URL)
.addConverterFactory(GsonConverterFactory.create())
.build()
val service = retrofit.create(GenreService::class.java)
return service.getGenres()
}
}

@ -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<List<Genre>>
}

@ -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 = ""
)

@ -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
)

@ -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<Movie>
)

@ -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 = ""
)

@ -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<Genre>
)

@ -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
}
}
}

@ -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<Genre>
}

@ -1,10 +0,0 @@
package fr.yobreuil.allomovies.data.persistance
import androidx.room.Dao
import androidx.room.Query
@Dao
interface MovieDao {
@Query("")
fun getAll();
}

@ -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<List<Genre>>
@Query("SELECT * FROM genres WHERE id = :id")
fun getById(id : Long) : LiveData<Genre>
@Query("SELECT")
fun getGenreWithMovies(idGenre : Long)
@Query("SELECT")
fun getMoviesByGenre(genreId: Long): LiveData<GenreWithMovies>
@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)
}

@ -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<List<Movie>>
@Query("SELECT * FROM movies ORDER BY movieName ASC")
fun getAllAlphabetical() : LiveData<List<Movie>>
@Query("SELECT * FROM movies ORDER BY movieName ASC")
fun getMoviesByGenre(genreId: Long) : LiveData<GenreWithMovies>;
}

@ -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<Genre> {
Log.i("GenreRepo", "FIND GENRE")
return genreDao.getById(genreId)
}
fun getAll(): LiveData<List<Genre>> {
Log.i("GenreRepo", "GET ALL GENRES")
return genreDao.getAll()
}
}

@ -0,0 +1,4 @@
package fr.yobreuil.allomovies.data.repositories
class MovieRepository {
}

@ -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?) {

@ -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()
}

@ -1,28 +1,38 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:card_view="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
card_view:cardUseCompatPadding="true">
xmlns:tools="http://schemas.android.com/tools">
<data>
<variable
name="genre"
type="fr.yobreuil.allomovies.data.entities.Genre" />
</data>
<LinearLayout
android:id="@+id/card_genre_component"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:orientation="vertical">
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="match_parent"
card_view:cardUseCompatPadding="true">
<ImageView
android:id="@+id/card_genre_image"
<LinearLayout
android:id="@+id/card_genre_component"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_launcher_foreground"/>
android:gravity="center_horizontal"
android:orientation="vertical">
<ImageView
android:id="@+id/card_genre_image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_launcher_foreground"/>
<TextView
android:id="@+id/card_genre_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{genre.genreName}"
tools:text="Genre's name"/>
</LinearLayout>
</androidx.cardview.widget.CardView>
</layout>
<TextView
android:id="@+id/card_genre_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
tools:text="Genre's name"/>
</LinearLayout>
</androidx.cardview.widget.CardView>

@ -1,23 +1,27 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.fragment.GenreListFragment">
xmlns:tools="http://schemas.android.com/tools">
<androidx.recyclerview.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layoutManager="androidx.recyclerview.widget.GridLayoutManager"
app:spanCount="2"
tools:listitem="@layout/card_genre">
<data>
<variable
name="genreListVM"
type="fr.yobreuil.allomovies.ui.viewmodel.GenreViewModel" />
</data>
</androidx.recyclerview.widget.RecyclerView>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.constraintlayout.widget.Group
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<view class="androidx.appcompat.app.AlertController$RecycleListView"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layoutManager="androidx.recyclerview.widget.GridLayoutManager"
app:spanCount="2"
tools:listitem="@layout/card_genre">
</view>
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>

@ -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
}
Loading…
Cancel
Save