🚧 first request from api

features/retrofit/1
Jordan ARTZET 2 years ago
parent 3cfc7d73b4
commit 904a5078ef

@ -66,10 +66,13 @@ dependencies {
// Moshi // Moshi
implementation "com.squareup.moshi:moshi-kotlin:1.13.0" implementation "com.squareup.moshi:moshi-kotlin:1.13.0"
//GSON
//implementation 'com.squareup.retrofit2:converter-gson:2.1.0'
// Retrofit // Retrofit
implementation "com.squareup.retrofit2:retrofit:2.9.0" implementation "com.squareup.retrofit2:retrofit:2.9.0"
// Retrofit with Scalar Converter // Retrofit with Scalar Converter
implementation "com.squareup.retrofit2:converter-scalars:2.9.0" //implementation "com.squareup.retrofit2:converter-scalars:2.9.0"
// Retrofit with Moshi Converter // Retrofit with Moshi Converter
implementation "com.squareup.retrofit2:converter-moshi:2.9.0" implementation "com.squareup.retrofit2:converter-moshi:2.9.0"

@ -1,18 +1,18 @@
package fr.iut.pm.movieapplication.api package fr.iut.pm.movieapplication.api
import fr.iut.pm.movieapplication.network.dtos.PopularDTO import fr.iut.pm.movieapplication.api.dtos.MovieResultDTO
import fr.iut.pm.movieapplication.utils.Constants import fr.iut.pm.movieapplication.api.dtos.PopularDTO
import fr.iut.pm.movieapplication.utils.Constants.Companion.API_KEY
import kotlinx.coroutines.flow.Flow
import retrofit2.Call import retrofit2.Call
import retrofit2.Response
import retrofit2.http.GET import retrofit2.http.GET
import retrofit2.http.Header import retrofit2.http.Path
import retrofit2.http.Query import retrofit2.http.Query
interface MovieApplicationAPI { interface MovieApplicationAPI {
@GET("movie/popular") @GET("movie/popular")
suspend fun getPopularMovies(@Query("api_key") apiKey : String) : Call<PopularDTO> fun getPopularMovies(@Query("api_key") apiKey : String) : Call<PopularDTO>
@GET("movie/{movie_id")
fun getMovieDetails(@Path("movie_id") movieId : Int, @Query("api_key") apiKey: String) : Call<MovieResultDTO>
} }

@ -6,22 +6,18 @@ import fr.iut.pm.movieapplication.utils.Constants.Companion.BASE_URL
import retrofit2.Retrofit import retrofit2.Retrofit
import retrofit2.converter.moshi.MoshiConverterFactory import retrofit2.converter.moshi.MoshiConverterFactory
private val moshi = Moshi.Builder()
.add(KotlinJsonAdapterFactory())
.build()
object RetrofitInstance { object RetrofitInstance {
private val retrofit by lazy { private val moshi = Moshi.Builder()
Retrofit.Builder() .add(KotlinJsonAdapterFactory())
.build()
private val retrofit = Retrofit.Builder()
.baseUrl("https://api.themoviedb.org/3/")
.addConverterFactory(MoshiConverterFactory.create(moshi)) .addConverterFactory(MoshiConverterFactory.create(moshi))
.baseUrl(BASE_URL)
.build() .build()
}
val api : MovieApplicationAPI by lazy { val api = retrofit.create(MovieApplicationAPI::class.java)
retrofit.create(MovieApplicationAPI::class.java)
}
} }

@ -0,0 +1,44 @@
package fr.iut.pm.movieapplication.api.dtos
import androidx.room.ColumnInfo
import androidx.room.Embedded
import androidx.room.PrimaryKey
import androidx.room.Relation
import com.squareup.moshi.Json
import fr.iut.pm.movieapplication.model.Genre
import fr.iut.pm.movieapplication.model.ProductionCompany
import fr.iut.pm.movieapplication.model.ProductionCountry
import fr.iut.pm.movieapplication.network.dtos.GenreDTO
class MovieDTO (
val adult: Boolean,
val budget: Int,
val genres: Array<GenreDTO>?,
val homepage: String?,
val id: Int,
@Json(name = "original_language")
val originalLanguage: String,
@Json(name = "original_title")
val originalTitle: String,
val overview: String?,
val popularity: Double,
@Json(name = "poster_path")
val posterPath: String?,
@Json(name = "production_countries")
val productionCountries: Array<ProductionCountry>,
@Json(name = "release_date")
val releaseDate: String,
val revenue: Int,
val runtime: Int?,
//var spokenLanguages : Array<SpokenLanguage>,
val status: String,
@Json(name = "tag_line")
val tagLine: String?,
val title: String,
@Json(name = "vote_average")
val voteAverage: Double,
@Json(name = "vote_count")
val voteCount: Int,
val backdropPath: String?
){
}

@ -0,0 +1,40 @@
package fr.iut.pm.movieapplication.api.dtos
import com.squareup.moshi.Json
class MovieResultDTO(
@Json(name = "poster_path")
val posterPath : String?,
@Json(name = "adult")
val adult : Boolean,
@Json(name = "overview")
val overview : String,
@Json(name = "release_date")
val releaseDate : String?,
@Json(name = "genre_ids")
val genreIds : List<Int>?,
@Json(name = "id")
val id : Int,
@Json(name = "original_title")
val originalTitle : String?,
@Json(name = "original_language")
val originalLanguage : String?,
@Json(name = "title")
val title : String?,
@Json(name = "backdrop_path")
val backdropPath : String?,
@Json(name = "popularity")
val popularity : Double?,
@Json(name = "vote_count")
val voteCount : Int?,
val video : Boolean?,
@Json(name = "vote_average")
val voteAverage : Double?
) {
}

@ -0,0 +1,18 @@
package fr.iut.pm.movieapplication.api.dtos
import com.squareup.moshi.Json
class PopularDTO(
@Json(name = "page")
val page : Int,
@Json(name = "results")
val results : List<MovieResultDTO>,
@Json(name = "total_results")
val totalResults : Int,
@Json(name = "total_pages")
val totalPages : Int
) {}

@ -1,57 +1,50 @@
package fr.iut.pm.movieapplication.model package fr.iut.pm.movieapplication.model
import androidx.room.ColumnInfo import androidx.room.ColumnInfo
import androidx.room.Embedded
import androidx.room.Entity import androidx.room.Entity
import androidx.room.PrimaryKey import androidx.room.PrimaryKey
import androidx.room.Relation
import java.util.Date
@Entity(tableName = "movies_table") @Entity(tableName = "movies_table")
data class Movie( data class Movie(
@ColumnInfo(name = "adult") @ColumnInfo(name = "adult")
val adult: Boolean, val adult: Boolean,
@ColumnInfo(name = "budget") @ColumnInfo(name = "budget")
val budget: Int, val budget: Int?,
@ColumnInfo(name = "genres") @ColumnInfo(name = "genres")
val genres: Array<Genre>, val genres: Array<Genre>?,
@ColumnInfo(name = "homepage") @ColumnInfo(name = "homepage")
val homePage: String?, val homePage: String?,
@PrimaryKey @PrimaryKey
@ColumnInfo(name = "id") @ColumnInfo(name = "id")
val movieId: Int, val movieId: Int,
@ColumnInfo(name = "original_language") @ColumnInfo(name = "original_language")
val originalLanguage: String, val originalLanguage: String?,
@ColumnInfo(name = "original_title") @ColumnInfo(name = "original_title")
val originalTitle: String, val originalTitle: String?,
val overview: String?, val overview: String?,
val popularity: Int, val popularity: Double?,
@ColumnInfo(name = "poster_path") @ColumnInfo(name = "poster_path")
val posterPath : String?, val posterPath: String?,
@Embedded val productionCompanies: Array<ProductionCompany>?,
val productionCompanies: Array<ProductionCompany>,
@Relation(
parentColumn = "movieId",
entityColumn = ""
)
@ColumnInfo(name = "production_countries") @ColumnInfo(name = "production_countries")
val productionCountries: Array<ProductionCountry>, val productionCountries: Array<ProductionCountry>?,
@ColumnInfo(name = "release_date") @ColumnInfo(name = "release_date")
val releaseDate: Date, val releaseDate: String?,
val revenue: Int, val revenue: Int?,
val runtime: Int?, val runtime: Int?,
//var spokenLanguages : Array<SpokenLanguage>, //var spokenLanguages : Array<SpokenLanguage>,
val status: String, val status: String?,
@ColumnInfo(name = "tag_line") @ColumnInfo(name = "tag_line")
val tagLine: String?, val tagLine: String?,
val title: String, val title: String?,
@ColumnInfo(name = "vote_average") @ColumnInfo(name = "vote_average")
val voteAverage: Number, val voteAverage: Double?,
@ColumnInfo(name = "vote_count") @ColumnInfo(name = "vote_count")
val voteCount : Int val voteCount: Int?,
val backdropPath: String?
) { ) {
override fun equals(other: Any?): Boolean { override fun equals(other: Any?): Boolean {

@ -1,25 +0,0 @@
package fr.iut.pm.movieapplication.network.dtos
import com.squareup.moshi.Json
data class MovieDTO(
@Json(name = "poster_path")
val posterPath : String?,
val adult : Boolean,
val overview : String?,
@Json(name = "release_date")
val releaseDate : String,
@Json(name = "genre_ids")
val genreIds : List<Int>,
val id : Int,
@Json(name = "original_title")
val originalTitle : String,
@Json(name = "original_language")
val originalLanguage : String,
val title : String
) {
}

@ -1,12 +0,0 @@
package fr.iut.pm.movieapplication.network.dtos
import com.squareup.moshi.Json
data class PopularDTO(
val page : Int,
val results : List<MovieDTO>,
@Json(name = "total_pages")
val totalPages : Int,
@Json(name = "total_results")
val totalResults : Int
) {}

@ -1,15 +1,44 @@
package fr.iut.pm.movieapplication.repository package fr.iut.pm.movieapplication.repository
import fr.iut.pm.movieapplication.data.dao.MovieDAO import android.util.Log
import fr.iut.pm.movieapplication.api.RetrofitInstance
import fr.iut.pm.movieapplication.api.dtos.PopularDTO
import fr.iut.pm.movieapplication.model.Movie import fr.iut.pm.movieapplication.model.Movie
import fr.iut.pm.movieapplication.network.dtos.MovieDTO import fr.iut.pm.movieapplication.utils.Constants
import kotlinx.coroutines.flow.Flow import fr.iut.pm.movieapplication.utils.Constants.Companion.API_KEY
import kotlinx.coroutines.flow.combine import fr.iut.pm.movieapplication.utils.Mapper
import kotlinx.coroutines.flow.transform import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response
class MovieRepository() { class MovieRepository() {
suspend fun getPopularMovies() : List<MovieDTO>{ fun getPopularMovies(callback: (List<Movie>) -> Unit ) {
return PopularRepository().getPopular()!!.results
val listMovie : MutableList<Movie> = mutableListOf()
RetrofitInstance.api.getPopularMovies(API_KEY).enqueue(object :
Callback<PopularDTO> {
override fun onResponse(call: Call<PopularDTO>, response: Response<PopularDTO>) {
if (response.isSuccessful) {
Log.d("List :", response.body().toString())
val popularDTO = response.body()
val listMoviesDTO = popularDTO?.results
listMoviesDTO?.forEach {
val movie = Mapper.MapToMovie(it)
listMovie.add(movie)
Log.d("Movie ", movie.title!!)
}
}
callback(listMovie)
}
override fun onFailure(call: Call<PopularDTO>, t: Throwable) {
Log.d("Error failure", t.message.toString())
}
})
} }
} }

@ -2,9 +2,8 @@ package fr.iut.pm.movieapplication.repository
import android.util.Log import android.util.Log
import fr.iut.pm.movieapplication.api.RetrofitInstance import fr.iut.pm.movieapplication.api.RetrofitInstance
import fr.iut.pm.movieapplication.network.dtos.PopularDTO import fr.iut.pm.movieapplication.api.dtos.PopularDTO
import fr.iut.pm.movieapplication.utils.Constants.Companion.API_KEY import fr.iut.pm.movieapplication.utils.Constants.Companion.API_KEY
import kotlinx.coroutines.flow.Flow
import retrofit2.Call import retrofit2.Call
import retrofit2.Callback import retrofit2.Callback
import retrofit2.Response import retrofit2.Response
@ -12,22 +11,6 @@ import retrofit2.Response
class PopularRepository() { class PopularRepository() {
suspend fun getPopular(): PopularDTO? { suspend fun getPopular(): PopularDTO? {
throw NoSuchMethodError()
lateinit var popularDTO : PopularDTO
RetrofitInstance.api.getPopularMovies(API_KEY).enqueue(object : Callback<PopularDTO> {
override fun onResponse(call: Call<PopularDTO>, response: Response<PopularDTO>) {
if (response.isSuccessful) {
Log.d("RESPONSE ::", response.body()?.page.toString())
popularDTO = response.body()!!
}
}
override fun onFailure(call: Call<PopularDTO>, t: Throwable) {
TODO("Not yet implemented")
}
})
return popularDTO
} }
} }

@ -3,16 +3,14 @@ package fr.iut.pm.movieapplication.ui.adapter
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.widget.ImageView
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import fr.iut.pm.movieapplication.R import fr.iut.pm.movieapplication.model.Movie
import fr.iut.pm.movieapplication.network.dtos.MovieDTO
import fr.iut.pm.movieapplication.ui.activity.MainActivity import fr.iut.pm.movieapplication.ui.activity.MainActivity
class HomeItemAdapter( class HomeItemAdapter(
private val context : MainActivity, private val context: MainActivity,
private val layoutId : Int, private val layoutId: Int,
private val list : List<MovieDTO> private val list: List<Movie>
) : RecyclerView.Adapter<HomeItemAdapter.ViewHolder>() { ) : RecyclerView.Adapter<HomeItemAdapter.ViewHolder>() {
class ViewHolder(view : View) : RecyclerView.ViewHolder(view) { class ViewHolder(view : View) : RecyclerView.ViewHolder(view) {

@ -7,8 +7,8 @@ import android.view.ViewGroup
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import fr.iut.pm.movieapplication.R import fr.iut.pm.movieapplication.R
import fr.iut.pm.movieapplication.network.dtos.MovieDTO import fr.iut.pm.movieapplication.api.dtos.MovieResultDTO
import fr.iut.pm.movieapplication.network.dtos.PopularDTO import fr.iut.pm.movieapplication.model.Movie
import fr.iut.pm.movieapplication.ui.activity.MainActivity import fr.iut.pm.movieapplication.ui.activity.MainActivity
import fr.iut.pm.movieapplication.ui.adapter.HomeItemAdapter import fr.iut.pm.movieapplication.ui.adapter.HomeItemAdapter
import fr.iut.pm.movieapplication.ui.adapter.HomeItemDecoration import fr.iut.pm.movieapplication.ui.adapter.HomeItemDecoration
@ -23,12 +23,12 @@ class HomeSectionsFragment(private val context : MainActivity) : Fragment() {
//get the trends RecyclerView //get the trends RecyclerView
val homeTrendsRecyclerView = view?.findViewById<RecyclerView>(R.id.home_trends_recycler_view) val homeTrendsRecyclerView = view?.findViewById<RecyclerView>(R.id.home_trends_recycler_view)
homeTrendsRecyclerView?.adapter = HomeItemAdapter(context,R.layout.item_horizontal_home_page,ArrayList<MovieDTO>()) homeTrendsRecyclerView?.adapter = HomeItemAdapter(context,R.layout.item_horizontal_home_page,ArrayList<Movie>())
homeTrendsRecyclerView?.addItemDecoration(HomeItemDecoration()) homeTrendsRecyclerView?.addItemDecoration(HomeItemDecoration())
//get the popularity RecyclerView //get the popularity RecyclerView
val homePopularityRecyclerView = view?.findViewById<RecyclerView>(R.id.home_popularity_recycler_view) val homePopularityRecyclerView = view?.findViewById<RecyclerView>(R.id.home_popularity_recycler_view)
homePopularityRecyclerView?.adapter = HomeItemAdapter(context,R.layout.item_horizontal_home_page,ArrayList<MovieDTO>()) homePopularityRecyclerView?.adapter = HomeItemAdapter(context,R.layout.item_horizontal_home_page,ArrayList<Movie>())
homePopularityRecyclerView?.addItemDecoration(HomeItemDecoration()) homePopularityRecyclerView?.addItemDecoration(HomeItemDecoration())
//get the free RecyclerView //get the free RecyclerView

@ -6,43 +6,45 @@ import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels import androidx.fragment.app.viewModels
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.viewmodel.viewModelFactory import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.GridLayoutManager import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import fr.iut.pm.movieapplication.R import fr.iut.pm.movieapplication.R
import fr.iut.pm.movieapplication.data.dao.MovieDAO import fr.iut.pm.movieapplication.api.RetrofitInstance
import fr.iut.pm.movieapplication.network.dtos.MovieDTO import fr.iut.pm.movieapplication.model.Movie
import fr.iut.pm.movieapplication.network.dtos.PopularDTO
import fr.iut.pm.movieapplication.repository.MovieRepository import fr.iut.pm.movieapplication.repository.MovieRepository
import fr.iut.pm.movieapplication.ui.activity.MainActivity import fr.iut.pm.movieapplication.ui.activity.MainActivity
import fr.iut.pm.movieapplication.ui.adapter.CategoryItemDecoration import fr.iut.pm.movieapplication.ui.adapter.CategoryItemDecoration
import fr.iut.pm.movieapplication.ui.adapter.HomeItemAdapter import fr.iut.pm.movieapplication.ui.adapter.HomeItemAdapter
import fr.iut.pm.movieapplication.ui.adapter.HomeItemDecoration
import fr.iut.pm.movieapplication.ui.viewmodel.MoviesVM import fr.iut.pm.movieapplication.ui.viewmodel.MoviesVM
import fr.iut.pm.movieapplication.ui.viewmodel.MoviesVMFactory import fr.iut.pm.movieapplication.ui.viewmodel.MoviesVMFactory
import kotlinx.coroutines.awaitAll import fr.iut.pm.movieapplication.ui.viewmodel.viewModelFactory
import kotlinx.coroutines.runBlocking import kotlinx.coroutines.launch
class MoviesFragment( class MoviesFragment(
private val context : MainActivity private val context : MainActivity
) : Fragment() { ) : Fragment() {
private val moviesVM: MoviesVM by viewModels{ MoviesVMFactory(repository = MovieRepository())}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
val view = inflater.inflate(R.layout.fragment_movies, container, false) val view = inflater.inflate(R.layout.fragment_movies, container, false)
val viewModel by viewModels<MoviesVM> {
MoviesVMFactory(MovieRepository())
}
val repository = MovieRepository()
repository.getPopularMovies { listMovies ->
val moviesRecyclerView = view?.findViewById<RecyclerView>(R.id.movies_item_recycler_view) val moviesRecyclerView = view?.findViewById<RecyclerView>(R.id.movies_item_recycler_view)
moviesRecyclerView?.adapter = HomeItemAdapter(context, R.layout.item_vertical_fragment, listMovies)
moviesRecyclerView ?. layoutManager = GridLayoutManager (context, 2)
moviesRecyclerView?.addItemDecoration(CategoryItemDecoration())
}
moviesRecyclerView?.adapter = HomeItemAdapter(context, R.layout.item_vertical_fragment,viewModel.popularMovies.value!!)
moviesRecyclerView?.layoutManager = GridLayoutManager(context, 2)
moviesRecyclerView?.addItemDecoration(CategoryItemDecoration())
return view return view

@ -1,46 +1,37 @@
package fr.iut.pm.movieapplication.ui.viewmodel package fr.iut.pm.movieapplication.ui.viewmodel
import androidx.lifecycle.MutableLiveData import androidx.lifecycle.*
import androidx.lifecycle.ViewModel import fr.iut.pm.movieapplication.api.dtos.MovieResultDTO
import androidx.lifecycle.ViewModelProvider import fr.iut.pm.movieapplication.model.Movie
import androidx.lifecycle.viewModelScope
import fr.iut.pm.movieapplication.network.dtos.MovieDTO
import fr.iut.pm.movieapplication.repository.MovieRepository import fr.iut.pm.movieapplication.repository.MovieRepository
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
class MoviesVM(private val repository: MovieRepository) : ViewModel() { class MoviesVM(private val repository: MovieRepository) : ViewModel() {
private val _popularMovies = MutableLiveData<List<MovieDTO>>() private val _popularMovies = MutableLiveData<List<Movie>>()
val popularMovies : MutableLiveData<List<MovieDTO>> = _popularMovies val popularMovies : LiveData<List<Movie>> = _popularMovies
init { init {
getPopularMovies() //loadData()
} }
suspend fun loadData() {
private fun getPopularMovies() {
viewModelScope.launch { viewModelScope.launch {
try { repository.getPopularMovies { movies ->
_popularMovies.value = repository.getPopularMovies()} _popularMovies.value = movies
catch (e : Exception) {
e.stackTrace
} }
}.join()
} }
}
} }
class MoviesVMFactory( class MoviesVMFactory(
private val repository: MovieRepository private val repository: MovieRepository
) : ViewModelProvider.Factory { ) : ViewModelProvider.Factory {
override fun <T : ViewModel> create(modelClass: Class<T>): T { override fun <T : ViewModel> create(modelClass: Class<T>): T {
if (modelClass.isAssignableFrom(MoviesVM::class.java)) {
return MoviesVM(repository) as T return MoviesVM(repository) as T
} }
throw java.lang.IllegalArgumentException("Unknown ViewModel class")
}
} }

@ -0,0 +1,9 @@
package fr.iut.pm.movieapplication.ui.viewmodel
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
inline fun <VM : ViewModel> viewModelFactory(crossinline f: () -> VM) =
object : ViewModelProvider.Factory {
override fun <T : ViewModel> create(modelClass: Class<T>): T = f() as T
}

@ -0,0 +1,36 @@
package fr.iut.pm.movieapplication.utils
import fr.iut.pm.movieapplication.api.dtos.MovieResultDTO
import fr.iut.pm.movieapplication.model.Movie
object Mapper {
fun MapToMovie( movieDTO : MovieResultDTO) : Movie {
return Movie(
adult = movieDTO.adult,
posterPath = movieDTO.posterPath,
overview = movieDTO.overview,
releaseDate = movieDTO.releaseDate,
movieId = movieDTO.id,
originalTitle = movieDTO.originalTitle,
originalLanguage = movieDTO.originalLanguage,
title = movieDTO.title,
backdropPath = movieDTO.backdropPath,
popularity = movieDTO.popularity,
voteCount = movieDTO.voteCount,
voteAverage = movieDTO.voteAverage,
budget = null,
genres = null,
homePage = null,
productionCompanies = null,
productionCountries = null,
revenue = null,
runtime = null,
status = null,
tagLine = null
)
}
}
Loading…
Cancel
Save