From 5d129c11df3ed4e33e8f6d783f890a12674f2fc7 Mon Sep 17 00:00:00 2001 From: hmalik144 Date: Tue, 13 Oct 2020 12:52:11 +0100 Subject: [PATCH] Initial commit --- .gitignore | 14 ++ .idea/.name | 1 + .idea/codeStyles/Project.xml | 122 +++++++++++++ .idea/codeStyles/codeStyleConfig.xml | 5 + .idea/dictionaries | 6 + .idea/gradle.xml | 21 +++ .idea/jarRepositories.xml | 25 +++ .idea/kotlinc.xml | 6 + .idea/misc.xml | 14 ++ .idea/runConfigurations.xml | 12 ++ app/.gitignore | 1 + app/build.gradle | 93 ++++++++++ app/proguard-rules.pro | 21 +++ .../movielisttest/ExampleInstrumentedTest.kt | 22 +++ .../data/room/MoviesRoomDatabaseTest.kt | 63 +++++++ app/src/main/AndroidManifest.xml | 25 +++ .../h_mal/movielisttest/MainActivity.kt | 18 ++ .../application/MovieListApplication.kt | 33 ++++ .../h_mal/movielisttest/data/models/Movie.kt | 26 +++ .../movielisttest/data/network/MoviesApi.kt | 49 +++++ .../NetworkConnectionInterceptor.kt | 42 +++++ .../interceptors/QueryParamsInterceptor.kt | 30 +++ .../data/network/networkUtils/OkHttpClient.kt | 21 +++ .../network/networkUtils/ResponseUnwrap.kt | 37 ++++ .../data/network/response/MoviesResponse.kt | 18 ++ .../data/network/response/ResultsItem.kt | 48 +++++ .../data/prefs/PreferencesProvider.kt | 33 ++++ .../data/repository/Repository.kt | 15 ++ .../data/repository/RepositoryImpl.kt | 36 ++++ .../movielisttest/data/room/MovieEntity.kt | 29 +++ .../data/room/MoviesRoomDatabase.kt | 40 ++++ .../movielisttest/data/room/SimpleDao.kt | 32 ++++ .../movielisttest/ui/main/MainFragment.kt | 80 ++++++++ .../movielisttest/ui/main/MainViewModel.kt | 87 +++++++++ .../ui/main/MainViewModelFactory.kt | 22 +++ .../ui/main/MoviesRecyclerViewAdapter.kt | 82 +++++++++ .../h_mal/movielisttest/utils/Event.kt | 24 +++ .../h_mal/movielisttest/utils/ViewUtils.kt | 41 +++++ .../drawable-v24/ic_launcher_foreground.xml | 30 +++ .../res/drawable/ic_launcher_background.xml | 170 +++++++++++++++++ app/src/main/res/drawable/mad_max_sample.jpg | Bin 0 -> 84103 bytes app/src/main/res/layout/empty_view_item.xml | 44 +++++ app/src/main/res/layout/item_layout.xml | 112 ++++++++++++ app/src/main/res/layout/main_activity.xml | 7 + app/src/main/res/layout/main_fragment.xml | 41 +++++ app/src/main/res/layout/simple_item.xml | 46 +++++ .../res/mipmap-anydpi-v26/ic_launcher.xml | 5 + .../mipmap-anydpi-v26/ic_launcher_round.xml | 5 + app/src/main/res/mipmap-hdpi/ic_launcher.png | Bin 0 -> 3593 bytes .../res/mipmap-hdpi/ic_launcher_round.png | Bin 0 -> 5339 bytes app/src/main/res/mipmap-mdpi/ic_launcher.png | Bin 0 -> 2636 bytes .../res/mipmap-mdpi/ic_launcher_round.png | Bin 0 -> 3388 bytes app/src/main/res/mipmap-xhdpi/ic_launcher.png | Bin 0 -> 4926 bytes .../res/mipmap-xhdpi/ic_launcher_round.png | Bin 0 -> 7472 bytes .../main/res/mipmap-xxhdpi/ic_launcher.png | Bin 0 -> 7909 bytes .../res/mipmap-xxhdpi/ic_launcher_round.png | Bin 0 -> 11873 bytes .../main/res/mipmap-xxxhdpi/ic_launcher.png | Bin 0 -> 10652 bytes .../res/mipmap-xxxhdpi/ic_launcher_round.png | Bin 0 -> 16570 bytes app/src/main/res/values/colors.xml | 6 + app/src/main/res/values/strings.xml | 6 + app/src/main/res/values/styles.xml | 15 ++ .../data/repository/RepositoryImplTest.kt | 73 ++++++++ .../data/room/MoviesRoomDatabaseTest.kt | 2 + .../ui/main/MainViewModelTest.kt | 112 ++++++++++++ build.gradle | 26 +++ gradle.properties | 23 +++ gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 54329 bytes gradle/wrapper/gradle-wrapper.properties | 6 + gradlew | 172 ++++++++++++++++++ gradlew.bat | 84 +++++++++ settings.gradle | 2 + 71 files changed, 2281 insertions(+) create mode 100644 .gitignore create mode 100644 .idea/.name create mode 100644 .idea/codeStyles/Project.xml create mode 100644 .idea/codeStyles/codeStyleConfig.xml create mode 100644 .idea/dictionaries create mode 100644 .idea/gradle.xml create mode 100644 .idea/jarRepositories.xml create mode 100644 .idea/kotlinc.xml create mode 100644 .idea/misc.xml create mode 100644 .idea/runConfigurations.xml create mode 100644 app/.gitignore create mode 100644 app/build.gradle create mode 100644 app/proguard-rules.pro create mode 100644 app/src/androidTest/java/com/example/h_mal/movielisttest/ExampleInstrumentedTest.kt create mode 100644 app/src/androidTest/java/com/example/h_mal/movielisttest/data/room/MoviesRoomDatabaseTest.kt create mode 100644 app/src/main/AndroidManifest.xml create mode 100644 app/src/main/java/com/example/h_mal/movielisttest/MainActivity.kt create mode 100644 app/src/main/java/com/example/h_mal/movielisttest/application/MovieListApplication.kt create mode 100644 app/src/main/java/com/example/h_mal/movielisttest/data/models/Movie.kt create mode 100644 app/src/main/java/com/example/h_mal/movielisttest/data/network/MoviesApi.kt create mode 100644 app/src/main/java/com/example/h_mal/movielisttest/data/network/interceptors/NetworkConnectionInterceptor.kt create mode 100644 app/src/main/java/com/example/h_mal/movielisttest/data/network/interceptors/QueryParamsInterceptor.kt create mode 100644 app/src/main/java/com/example/h_mal/movielisttest/data/network/networkUtils/OkHttpClient.kt create mode 100644 app/src/main/java/com/example/h_mal/movielisttest/data/network/networkUtils/ResponseUnwrap.kt create mode 100644 app/src/main/java/com/example/h_mal/movielisttest/data/network/response/MoviesResponse.kt create mode 100644 app/src/main/java/com/example/h_mal/movielisttest/data/network/response/ResultsItem.kt create mode 100644 app/src/main/java/com/example/h_mal/movielisttest/data/prefs/PreferencesProvider.kt create mode 100644 app/src/main/java/com/example/h_mal/movielisttest/data/repository/Repository.kt create mode 100644 app/src/main/java/com/example/h_mal/movielisttest/data/repository/RepositoryImpl.kt create mode 100644 app/src/main/java/com/example/h_mal/movielisttest/data/room/MovieEntity.kt create mode 100644 app/src/main/java/com/example/h_mal/movielisttest/data/room/MoviesRoomDatabase.kt create mode 100644 app/src/main/java/com/example/h_mal/movielisttest/data/room/SimpleDao.kt create mode 100644 app/src/main/java/com/example/h_mal/movielisttest/ui/main/MainFragment.kt create mode 100644 app/src/main/java/com/example/h_mal/movielisttest/ui/main/MainViewModel.kt create mode 100644 app/src/main/java/com/example/h_mal/movielisttest/ui/main/MainViewModelFactory.kt create mode 100644 app/src/main/java/com/example/h_mal/movielisttest/ui/main/MoviesRecyclerViewAdapter.kt create mode 100644 app/src/main/java/com/example/h_mal/movielisttest/utils/Event.kt create mode 100644 app/src/main/java/com/example/h_mal/movielisttest/utils/ViewUtils.kt create mode 100644 app/src/main/res/drawable-v24/ic_launcher_foreground.xml create mode 100644 app/src/main/res/drawable/ic_launcher_background.xml create mode 100644 app/src/main/res/drawable/mad_max_sample.jpg create mode 100644 app/src/main/res/layout/empty_view_item.xml create mode 100644 app/src/main/res/layout/item_layout.xml create mode 100644 app/src/main/res/layout/main_activity.xml create mode 100644 app/src/main/res/layout/main_fragment.xml create mode 100644 app/src/main/res/layout/simple_item.xml create mode 100644 app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml create mode 100644 app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml create mode 100644 app/src/main/res/mipmap-hdpi/ic_launcher.png create mode 100644 app/src/main/res/mipmap-hdpi/ic_launcher_round.png create mode 100644 app/src/main/res/mipmap-mdpi/ic_launcher.png create mode 100644 app/src/main/res/mipmap-mdpi/ic_launcher_round.png create mode 100644 app/src/main/res/mipmap-xhdpi/ic_launcher.png create mode 100644 app/src/main/res/mipmap-xhdpi/ic_launcher_round.png create mode 100644 app/src/main/res/mipmap-xxhdpi/ic_launcher.png create mode 100644 app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png create mode 100644 app/src/main/res/mipmap-xxxhdpi/ic_launcher.png create mode 100644 app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png create mode 100644 app/src/main/res/values/colors.xml create mode 100644 app/src/main/res/values/strings.xml create mode 100644 app/src/main/res/values/styles.xml create mode 100644 app/src/test/java/com/example/h_mal/movielisttest/data/repository/RepositoryImplTest.kt create mode 100644 app/src/test/java/com/example/h_mal/movielisttest/data/room/MoviesRoomDatabaseTest.kt create mode 100644 app/src/test/java/com/example/h_mal/movielisttest/ui/main/MainViewModelTest.kt create mode 100644 build.gradle create mode 100644 gradle.properties create mode 100644 gradle/wrapper/gradle-wrapper.jar create mode 100644 gradle/wrapper/gradle-wrapper.properties create mode 100644 gradlew create mode 100644 gradlew.bat create mode 100644 settings.gradle diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..603b140 --- /dev/null +++ b/.gitignore @@ -0,0 +1,14 @@ +*.iml +.gradle +/local.properties +/.idea/caches +/.idea/libraries +/.idea/modules.xml +/.idea/workspace.xml +/.idea/navEditor.xml +/.idea/assetWizardSettings.xml +.DS_Store +/build +/captures +.externalNativeBuild +.cxx diff --git a/.idea/.name b/.idea/.name new file mode 100644 index 0000000..38f564c --- /dev/null +++ b/.idea/.name @@ -0,0 +1 @@ +MovieListTest \ No newline at end of file diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml new file mode 100644 index 0000000..88ea3aa --- /dev/null +++ b/.idea/codeStyles/Project.xml @@ -0,0 +1,122 @@ + + + + + + + + + +
+ + + + xmlns:android + + ^$ + + + +
+
+ + + + xmlns:.* + + ^$ + + + BY_NAME + +
+
+ + + + .*:id + + http://schemas.android.com/apk/res/android + + + +
+
+ + + + .*:name + + http://schemas.android.com/apk/res/android + + + +
+
+ + + + name + + ^$ + + + +
+
+ + + + style + + ^$ + + + +
+
+ + + + .* + + ^$ + + + BY_NAME + +
+
+ + + + .* + + http://schemas.android.com/apk/res/android + + + ANDROID_ATTRIBUTE_ORDER + +
+
+ + + + .* + + .* + + + BY_NAME + +
+
+
+
+ + +
+
\ No newline at end of file diff --git a/.idea/codeStyles/codeStyleConfig.xml b/.idea/codeStyles/codeStyleConfig.xml new file mode 100644 index 0000000..79ee123 --- /dev/null +++ b/.idea/codeStyles/codeStyleConfig.xml @@ -0,0 +1,5 @@ + + + + \ No newline at end of file diff --git a/.idea/dictionaries b/.idea/dictionaries new file mode 100644 index 0000000..ed3680a --- /dev/null +++ b/.idea/dictionaries @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/gradle.xml b/.idea/gradle.xml new file mode 100644 index 0000000..ac6b0ae --- /dev/null +++ b/.idea/gradle.xml @@ -0,0 +1,21 @@ + + + + + + + \ No newline at end of file diff --git a/.idea/jarRepositories.xml b/.idea/jarRepositories.xml new file mode 100644 index 0000000..a5f05cd --- /dev/null +++ b/.idea/jarRepositories.xml @@ -0,0 +1,25 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/kotlinc.xml b/.idea/kotlinc.xml new file mode 100644 index 0000000..8b7f4af --- /dev/null +++ b/.idea/kotlinc.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..703e5d4 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/runConfigurations.xml b/.idea/runConfigurations.xml new file mode 100644 index 0000000..7f68460 --- /dev/null +++ b/.idea/runConfigurations.xml @@ -0,0 +1,12 @@ + + + + + + \ No newline at end of file diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..2c388c7 --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,93 @@ +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-android-extensions' +apply plugin: 'kotlin-kapt' + +android { + compileSdkVersion 30 + buildToolsVersion "29.0.3" + + defaultConfig { + applicationId "com.example.h_mal.movielisttest" + minSdkVersion 23 + targetSdkVersion 30 + versionCode 1 + versionName "1.0" + + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + buildConfigField "String", "ParamOne", "${paramOne}" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + // To inline the bytecode built with JVM target 1.8 into + // bytecode that is being built with JVM target 1.6. (e.g. navArgs) + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + kotlinOptions { + jvmTarget = "1.8" + } +} + +dependencies { + implementation fileTree(dir: "libs", include: ["*.jar"]) + implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" + implementation 'androidx.core:core-ktx:1.3.2' + implementation 'androidx.appcompat:appcompat:1.2.0' + implementation 'androidx.constraintlayout:constraintlayout:2.0.2' + implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0' + implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.2.0' + implementation 'androidx.fragment:fragment-ktx:1.2.5' + implementation 'com.google.android.material:material:1.2.1' + implementation 'androidx.legacy:legacy-support-v4:1.0.0' + testImplementation 'junit:junit:4.13' + androidTestImplementation 'junit:junit:4.12' + androidTestImplementation 'androidx.test.ext:junit:1.1.2' + androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0' + // android unit testing and espresso + androidTestImplementation 'androidx.test.ext:junit:1.1.2' + implementation 'androidx.test.espresso:espresso-core:3.3.0' + androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0' + testImplementation "org.jetbrains.kotlin:kotlin-test-junit:$kotlin_version" + //mock websever for testing retrofit responses + testImplementation "com.squareup.okhttp3:mockwebserver:4.6.0" + testImplementation "com.nhaarman.mockitokotlin2:mockito-kotlin:2.2.0" + + //mockito and livedata testing + testImplementation 'org.mockito:mockito-inline:2.13.0' + implementation 'android.arch.core:core-testing' + androidTestImplementation 'androidx.test:rules:1.3.0' + + //Retrofit and GSON + implementation 'com.squareup.retrofit2:retrofit:2.8.1' + implementation 'com.squareup.retrofit2:converter-gson:2.8.1' + implementation 'com.squareup.okhttp3:logging-interceptor:4.0.0' + + //Kotlin Coroutines + implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.4" + implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.4" + + //Kodein Dependency Injection + implementation "org.kodein.di:kodein-di-generic-jvm:6.2.1" + implementation "org.kodein.di:kodein-di-framework-android-x:6.2.1" + + // Shared prefs + implementation "androidx.preference:preference-ktx:1.1.1" + + // Picasso image display + implementation 'com.squareup.picasso:picasso:2.71828' + + //Android Room + implementation "androidx.room:room-runtime:2.3.0-alpha01" + implementation "androidx.room:room-ktx:2.3.0-alpha01" + kapt "androidx.room:room-compiler:2.3.0-alpha01" + + // Circle Image View + implementation 'com.mikhaellopez:circularimageview:4.2.0' +} \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/app/src/androidTest/java/com/example/h_mal/movielisttest/ExampleInstrumentedTest.kt b/app/src/androidTest/java/com/example/h_mal/movielisttest/ExampleInstrumentedTest.kt new file mode 100644 index 0000000..cffc845 --- /dev/null +++ b/app/src/androidTest/java/com/example/h_mal/movielisttest/ExampleInstrumentedTest.kt @@ -0,0 +1,22 @@ +package com.example.h_mal.movielisttest + +import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.test.platform.app.InstrumentationRegistry +import org.junit.Assert.assertEquals +import org.junit.Test +import org.junit.runner.RunWith + +/** + * Instrumented test, which will execute on an Android device. + * + * See [testing documentation](http://d.android.com/tools/testing). + */ +@RunWith(AndroidJUnit4::class) +class ExampleInstrumentedTest { + @Test + fun useAppContext() { + // Context of the app under test. + val appContext = InstrumentationRegistry.getInstrumentation().targetContext + assertEquals("com.example.h_mal.movielisttest", appContext.packageName) + } +} \ No newline at end of file diff --git a/app/src/androidTest/java/com/example/h_mal/movielisttest/data/room/MoviesRoomDatabaseTest.kt b/app/src/androidTest/java/com/example/h_mal/movielisttest/data/room/MoviesRoomDatabaseTest.kt new file mode 100644 index 0000000..85c23da --- /dev/null +++ b/app/src/androidTest/java/com/example/h_mal/movielisttest/data/room/MoviesRoomDatabaseTest.kt @@ -0,0 +1,63 @@ +package com.example.h_mal.movielisttest.data.room + +import android.content.Context +import androidx.room.Room +import androidx.test.core.app.ApplicationProvider +import androidx.test.espresso.matcher.ViewMatchers.assertThat +import androidx.test.ext.junit.runners.AndroidJUnit4 +import kotlinx.coroutines.runBlocking +import org.hamcrest.CoreMatchers.equalTo +import org.junit.After +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith +import java.io.IOException + +@RunWith(AndroidJUnit4::class) +class MoviesRoomDatabaseTest{ + private lateinit var simpleDao: SimpleDao + private lateinit var db: MoviesRoomDatabase + + @Before + fun createDb() { + val context = ApplicationProvider.getApplicationContext() + db = Room.inMemoryDatabaseBuilder( + context, MoviesRoomDatabase::class.java).build() + simpleDao = db.getSimpleDao() + } + + @After + @Throws(IOException::class) + fun closeDb() { + db.close() + } + + @Test + @Throws(Exception::class) + fun writeEntryAndReadResponse() = runBlocking{ + // Given + val entity = MovieEntity(123) + // When + simpleDao.saveAllItems(listOf(entity)) + // Then + val retrieved = simpleDao.getItem(123) + assertThat(retrieved, equalTo(entity)) + } + + @Test + @Throws(Exception::class) + fun changeFavouriteAndRead() = runBlocking{ + // Given + val entity = MovieEntity(123) + simpleDao.saveAllItems(listOf(entity)) + val retrieved = simpleDao.getItem(123) + + // When + simpleDao.updateFavourite(123) + + // Then + val favourite = retrieved.favourites + val retrieveAgain = simpleDao.getItem(123) + assertThat(retrieveAgain.favourites, equalTo(!favourite)) + } +} \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..e860407 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/example/h_mal/movielisttest/MainActivity.kt b/app/src/main/java/com/example/h_mal/movielisttest/MainActivity.kt new file mode 100644 index 0000000..2313fe8 --- /dev/null +++ b/app/src/main/java/com/example/h_mal/movielisttest/MainActivity.kt @@ -0,0 +1,18 @@ +package com.example.h_mal.movielisttest + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import com.example.h_mal.movielisttest.ui.main.MainFragment + +class MainActivity : AppCompatActivity() { + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(R.layout.main_activity) + if (savedInstanceState == null) { + supportFragmentManager.beginTransaction() + .replace(R.id.container, MainFragment()) + .commitNow() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/h_mal/movielisttest/application/MovieListApplication.kt b/app/src/main/java/com/example/h_mal/movielisttest/application/MovieListApplication.kt new file mode 100644 index 0000000..ceba3ad --- /dev/null +++ b/app/src/main/java/com/example/h_mal/movielisttest/application/MovieListApplication.kt @@ -0,0 +1,33 @@ +package com.example.h_mal.movielisttest.application + +import android.app.Application +import com.example.h_mal.movielisttest.data.network.MoviesApi +import com.example.h_mal.movielisttest.data.network.interceptors.NetworkConnectionInterceptor +import com.example.h_mal.movielisttest.data.network.interceptors.QueryParamsInterceptor +import com.example.h_mal.movielisttest.data.prefs.PreferenceProvider +import com.example.h_mal.movielisttest.data.repository.RepositoryImpl +import com.example.h_mal.movielisttest.data.room.MoviesRoomDatabase +import com.example.h_mal.movielisttest.ui.main.MainViewModelFactory +import org.kodein.di.Kodein +import org.kodein.di.KodeinAware +import org.kodein.di.android.x.androidXModule +import org.kodein.di.generic.bind +import org.kodein.di.generic.instance +import org.kodein.di.generic.provider +import org.kodein.di.generic.singleton + +class MovieListApplication : Application(), KodeinAware{ + + // Kodein creation of modules to be retrieve within the app + override val kodein = Kodein.lazy { + import(androidXModule(this@MovieListApplication)) + + bind() from singleton { NetworkConnectionInterceptor(instance()) } + bind() from singleton { QueryParamsInterceptor() } + bind() from singleton { MoviesApi(instance(), instance())} + bind() from singleton { MoviesRoomDatabase(instance()) } + bind() from singleton { PreferenceProvider(instance()) } + bind() from singleton { RepositoryImpl(instance(), instance(), instance()) } + bind() from provider { MainViewModelFactory(instance()) } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/h_mal/movielisttest/data/models/Movie.kt b/app/src/main/java/com/example/h_mal/movielisttest/data/models/Movie.kt new file mode 100644 index 0000000..3604348 --- /dev/null +++ b/app/src/main/java/com/example/h_mal/movielisttest/data/models/Movie.kt @@ -0,0 +1,26 @@ +package com.example.h_mal.movielisttest.data.models + +import com.example.h_mal.movielisttest.data.room.MovieEntity + +data class Movie( + val id: Int? = null, + val overview: String? = null, + var favourites: Boolean? = null, + val title: String? = null, + val posterPath: String? = null, + val releaseDate: String? = null, + val popularity: Double? = null, + val voteAverage: Double? = null +){ + + constructor(movieEntity: MovieEntity): this( + movieEntity.id, + movieEntity.overview, + movieEntity.favourites, + movieEntity.title, + movieEntity.posterPath, + movieEntity.releaseDate, + movieEntity.popularity, + movieEntity.voteAverage + ) +} diff --git a/app/src/main/java/com/example/h_mal/movielisttest/data/network/MoviesApi.kt b/app/src/main/java/com/example/h_mal/movielisttest/data/network/MoviesApi.kt new file mode 100644 index 0000000..914cf8c --- /dev/null +++ b/app/src/main/java/com/example/h_mal/movielisttest/data/network/MoviesApi.kt @@ -0,0 +1,49 @@ +package com.example.h_mal.movielisttest.data.network + +import com.example.h_mal.movielisttest.data.network.interceptors.NetworkConnectionInterceptor +import com.example.h_mal.movielisttest.data.network.interceptors.QueryParamsInterceptor +import com.example.h_mal.movielisttest.data.network.response.MoviesResponse +import okhttp3.OkHttpClient +import okhttp3.logging.HttpLoggingInterceptor +import retrofit2.Response +import retrofit2.Retrofit +import retrofit2.converter.gson.GsonConverterFactory +import retrofit2.http.GET +import retrofit2.http.Query + + +interface MoviesApi { + + // https://api.themoviedb.org/3/movie/popular?api_key=&language=en-US&page=1 + @GET("movie/popular?") + suspend fun getFromApi( + @Query("page") pageNumber: Int + ): Response + + companion object{ + operator fun invoke( + networkConnectionInterceptor: NetworkConnectionInterceptor, + queryParamsInterceptor: QueryParamsInterceptor + ) : MoviesApi { + + val baseUrl = "https://api.themoviedb.org/3/" + + // okHttpClient + val okkHttpclient = OkHttpClient.Builder() + .addNetworkInterceptor(networkConnectionInterceptor) + .addInterceptor(queryParamsInterceptor) + .addInterceptor(HttpLoggingInterceptor().apply { + level = HttpLoggingInterceptor.Level.BODY + }) + .build() + + return Retrofit.Builder() + .client(okkHttpclient) + .baseUrl(baseUrl) + .addConverterFactory(GsonConverterFactory.create()) + .build() + .create(MoviesApi::class.java) + } + } +} + diff --git a/app/src/main/java/com/example/h_mal/movielisttest/data/network/interceptors/NetworkConnectionInterceptor.kt b/app/src/main/java/com/example/h_mal/movielisttest/data/network/interceptors/NetworkConnectionInterceptor.kt new file mode 100644 index 0000000..486a90c --- /dev/null +++ b/app/src/main/java/com/example/h_mal/movielisttest/data/network/interceptors/NetworkConnectionInterceptor.kt @@ -0,0 +1,42 @@ +package com.example.h_mal.movielisttest.data.network.interceptors + +import android.content.Context +import android.net.ConnectivityManager +import android.net.NetworkCapabilities +import okhttp3.Interceptor +import java.io.IOException + +/** + * Intercept API calls and determine if there is a connection. + * If no connection then @throws IOException + */ +class NetworkConnectionInterceptor( + context: Context +) : Interceptor { + + private val applicationContext = context.applicationContext + + override fun intercept(chain: Interceptor.Chain): okhttp3.Response { + if (!isInternetAvailable()){ + throw IOException("Make sure you have an active data connection") + } + return chain.proceed(chain.request()) + } + + private fun isInternetAvailable(): Boolean { + var result = false + val connectivityManager = + applicationContext.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager? + connectivityManager?.let { + it.getNetworkCapabilities(connectivityManager.activeNetwork)?.apply { + result = when { + hasTransport(NetworkCapabilities.TRANSPORT_WIFI) -> true + hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) -> true + else -> false + } + } + } + return result + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/example/h_mal/movielisttest/data/network/interceptors/QueryParamsInterceptor.kt b/app/src/main/java/com/example/h_mal/movielisttest/data/network/interceptors/QueryParamsInterceptor.kt new file mode 100644 index 0000000..808f898 --- /dev/null +++ b/app/src/main/java/com/example/h_mal/movielisttest/data/network/interceptors/QueryParamsInterceptor.kt @@ -0,0 +1,30 @@ +package com.example.h_mal.movielisttest.data.network.interceptors + +import com.example.h_mal.movielisttest.BuildConfig +import okhttp3.Interceptor +import okhttp3.Request +import okhttp3.Response + +/** + * Inject query parameters into the API calls. + * For uniform constraints (eg. Language, sort order, page size ect) + * Also for injecting an API key to all api calls + */ +class QueryParamsInterceptor : Interceptor{ + + override fun intercept(chain: Interceptor.Chain): Response { + val original = chain.request() + val originalHttpUrl = original.url + + val url = originalHttpUrl.newBuilder() + .addQueryParameter("language", "en-UK") + .addQueryParameter("api_key", BuildConfig.ParamOne) + .build() + + val requestBuilder: Request.Builder = original.newBuilder() + .url(url) + + val request: Request = requestBuilder.build() + return chain.proceed(request) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/h_mal/movielisttest/data/network/networkUtils/OkHttpClient.kt b/app/src/main/java/com/example/h_mal/movielisttest/data/network/networkUtils/OkHttpClient.kt new file mode 100644 index 0000000..f4fba7c --- /dev/null +++ b/app/src/main/java/com/example/h_mal/movielisttest/data/network/networkUtils/OkHttpClient.kt @@ -0,0 +1,21 @@ +package com.example.h_mal.movielisttest.data.network.networkUtils + +import com.example.h_mal.movielisttest.data.network.interceptors.NetworkConnectionInterceptor +import okhttp3.OkHttpClient +import okhttp3.logging.HttpLoggingInterceptor +import java.util.concurrent.TimeUnit + +fun okHttpClient( + networkConnectionInterceptor: NetworkConnectionInterceptor + +): OkHttpClient { + val logging: HttpLoggingInterceptor = HttpLoggingInterceptor().apply { + level = HttpLoggingInterceptor.Level.BODY + } + + return OkHttpClient.Builder() + .addNetworkInterceptor(networkConnectionInterceptor) + .addInterceptor(logging) + .readTimeout(5 * 60, TimeUnit.SECONDS) + .build() +} \ No newline at end of file diff --git a/app/src/main/java/com/example/h_mal/movielisttest/data/network/networkUtils/ResponseUnwrap.kt b/app/src/main/java/com/example/h_mal/movielisttest/data/network/networkUtils/ResponseUnwrap.kt new file mode 100644 index 0000000..f49b633 --- /dev/null +++ b/app/src/main/java/com/example/h_mal/movielisttest/data/network/networkUtils/ResponseUnwrap.kt @@ -0,0 +1,37 @@ +package com.example.h_mal.movielisttest.data.network.networkUtils + +import org.json.JSONException +import org.json.JSONObject +import retrofit2.Response +import java.io.IOException + +/** + * Abstract class for extracting from Retrofit Response + * Or throw IOException if the API call fails + */ +abstract class ResponseUnwrap { + + @Suppress("BlockingMethodInNonBlockingContext") + suspend fun responseUnwrap( + call: suspend () -> Response + ): T { + + val response = call.invoke() + if (response.isSuccessful) { + return response.body()!! + } else { + val error = response.errorBody()?.string() + + val errorMessage = error?.let { + try { + JSONObject(it).getString("status_message") + } catch (e: JSONException) { + e.printStackTrace() + null + } + } ?: "Error Code: ${response.code()}" + + throw IOException(errorMessage) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/h_mal/movielisttest/data/network/response/MoviesResponse.kt b/app/src/main/java/com/example/h_mal/movielisttest/data/network/response/MoviesResponse.kt new file mode 100644 index 0000000..07741ce --- /dev/null +++ b/app/src/main/java/com/example/h_mal/movielisttest/data/network/response/MoviesResponse.kt @@ -0,0 +1,18 @@ +package com.example.h_mal.movielisttest.data.network.response + +import com.google.gson.annotations.SerializedName + +data class MoviesResponse( + + @field:SerializedName("page") + val page: Int? = null, + + @field:SerializedName("total_pages") + val totalPages: Int? = null, + + @field:SerializedName("results") + val results: List? = null, + + @field:SerializedName("total_results") + val totalResults: Int? = null +) \ No newline at end of file diff --git a/app/src/main/java/com/example/h_mal/movielisttest/data/network/response/ResultsItem.kt b/app/src/main/java/com/example/h_mal/movielisttest/data/network/response/ResultsItem.kt new file mode 100644 index 0000000..b71b0f4 --- /dev/null +++ b/app/src/main/java/com/example/h_mal/movielisttest/data/network/response/ResultsItem.kt @@ -0,0 +1,48 @@ +package com.example.h_mal.movielisttest.data.network.response + +import com.google.gson.annotations.SerializedName + +data class ResultsItem( + + @field:SerializedName("overview") + val overview: String? = null, + + @field:SerializedName("original_language") + val originalLanguage: String? = null, + + @field:SerializedName("original_title") + val originalTitle: String? = null, + + @field:SerializedName("video") + val video: Boolean? = null, + + @field:SerializedName("title") + val title: String? = null, + + @field:SerializedName("genre_ids") + val genreIds: List? = null, + + @field:SerializedName("poster_path") + val posterPath: String? = null, + + @field:SerializedName("backdrop_path") + val backdropPath: String? = null, + + @field:SerializedName("release_date") + val releaseDate: String? = null, + + @field:SerializedName("popularity") + val popularity: Double? = null, + + @field:SerializedName("vote_average") + val voteAverage: Double? = null, + + @field:SerializedName("id") + val id: Int? = null, + + @field:SerializedName("adult") + val adult: Boolean? = null, + + @field:SerializedName("vote_count") + val voteCount: Int? = null +) \ No newline at end of file diff --git a/app/src/main/java/com/example/h_mal/movielisttest/data/prefs/PreferencesProvider.kt b/app/src/main/java/com/example/h_mal/movielisttest/data/prefs/PreferencesProvider.kt new file mode 100644 index 0000000..aa8f578 --- /dev/null +++ b/app/src/main/java/com/example/h_mal/movielisttest/data/prefs/PreferencesProvider.kt @@ -0,0 +1,33 @@ +package com.example.h_mal.movielisttest.data.prefs + +import android.content.Context +import android.content.SharedPreferences +import androidx.preference.PreferenceManager + +/** + * Shared preferences to save & load last timestamp + */ +private const val PAGE_NUMBER = "page_number" +class PreferenceProvider( + context: Context +) { + + private val appContext = context.applicationContext + + private val preference: SharedPreferences + get() = PreferenceManager.getDefaultSharedPreferences(appContext) + + fun savePageNumber() { + var pages = getPageNumber() + pages++ + preference.edit().putInt( + PAGE_NUMBER, + pages + ).apply() + } + + fun getPageNumber(): Int { + return preference.getInt(PAGE_NUMBER, 1) + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/example/h_mal/movielisttest/data/repository/Repository.kt b/app/src/main/java/com/example/h_mal/movielisttest/data/repository/Repository.kt new file mode 100644 index 0000000..18cb10d --- /dev/null +++ b/app/src/main/java/com/example/h_mal/movielisttest/data/repository/Repository.kt @@ -0,0 +1,15 @@ +package com.example.h_mal.movielisttest.data.repository + +import androidx.lifecycle.LiveData +import com.example.h_mal.movielisttest.data.network.response.MoviesResponse +import com.example.h_mal.movielisttest.data.network.response.ResultsItem +import com.example.h_mal.movielisttest.data.room.MovieEntity + +interface Repository { + suspend fun getMoviesFromApi(pageNumber: Int): MoviesResponse? + fun getMoviesFromDatabase(): LiveData> + suspend fun saveMoviesToDatabase(resultsItems: List) + suspend fun setFavourite(id: Int) + fun getCurrentPage(): Int + fun updateCurrentPage() +} diff --git a/app/src/main/java/com/example/h_mal/movielisttest/data/repository/RepositoryImpl.kt b/app/src/main/java/com/example/h_mal/movielisttest/data/repository/RepositoryImpl.kt new file mode 100644 index 0000000..91bf5a0 --- /dev/null +++ b/app/src/main/java/com/example/h_mal/movielisttest/data/repository/RepositoryImpl.kt @@ -0,0 +1,36 @@ +package com.example.h_mal.movielisttest.data.repository + +import com.example.h_mal.movielisttest.data.network.MoviesApi +import com.example.h_mal.movielisttest.data.network.networkUtils.ResponseUnwrap +import com.example.h_mal.movielisttest.data.network.response.MoviesResponse +import com.example.h_mal.movielisttest.data.network.response.ResultsItem +import com.example.h_mal.movielisttest.data.prefs.PreferenceProvider +import com.example.h_mal.movielisttest.data.room.MovieEntity +import com.example.h_mal.movielisttest.data.room.MoviesRoomDatabase + +class RepositoryImpl( + private val api: MoviesApi, + private val database: MoviesRoomDatabase, + private val preferences: PreferenceProvider +) : Repository, ResponseUnwrap() { + + + override suspend fun getMoviesFromApi(pageNumber: Int): MoviesResponse? { + return responseUnwrap { api.getFromApi(pageNumber) } + } + + override fun getMoviesFromDatabase() = database.getSimpleDao().getAllItems() + + override suspend fun saveMoviesToDatabase(resultsItems: List){ + val userList = resultsItems.map { MovieEntity(it) } + database.getSimpleDao().saveAllItems(userList) + } + + override suspend fun setFavourite(id: Int) = database.getSimpleDao().updateFavourite(id) + + override fun getCurrentPage(): Int = preferences.getPageNumber() + + override fun updateCurrentPage(){ + preferences.savePageNumber() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/h_mal/movielisttest/data/room/MovieEntity.kt b/app/src/main/java/com/example/h_mal/movielisttest/data/room/MovieEntity.kt new file mode 100644 index 0000000..8575383 --- /dev/null +++ b/app/src/main/java/com/example/h_mal/movielisttest/data/room/MovieEntity.kt @@ -0,0 +1,29 @@ +package com.example.h_mal.movielisttest.data.room + +import androidx.room.Entity +import androidx.room.PrimaryKey +import com.example.h_mal.movielisttest.data.network.response.ResultsItem + +@Entity +data class MovieEntity( + @PrimaryKey(autoGenerate = false) + val id: Int, + val overview: String? = null, + var favourites: Boolean = false, + val title: String? = null, + val posterPath: String? = null, + val releaseDate: String? = null, + val popularity: Double? = null, + val voteAverage: Double? = null +){ + constructor(resultsItem: ResultsItem): this( + resultsItem.id!!, + resultsItem.overview, + false, + resultsItem.title, + "https://image.tmdb.org/t/p/w500${resultsItem.posterPath}", + resultsItem.releaseDate, + resultsItem.popularity, + resultsItem.voteAverage + ) +} \ No newline at end of file diff --git a/app/src/main/java/com/example/h_mal/movielisttest/data/room/MoviesRoomDatabase.kt b/app/src/main/java/com/example/h_mal/movielisttest/data/room/MoviesRoomDatabase.kt new file mode 100644 index 0000000..73d08dc --- /dev/null +++ b/app/src/main/java/com/example/h_mal/movielisttest/data/room/MoviesRoomDatabase.kt @@ -0,0 +1,40 @@ +package com.example.h_mal.movielisttest.data.room + +import android.content.Context +import androidx.room.Database +import androidx.room.Room +import androidx.room.RoomDatabase + + +/** + * Room database class for caching movies locally. + */ +@Database( + entities = [MovieEntity::class], + version = 1 +) +abstract class MoviesRoomDatabase : RoomDatabase() { + + abstract fun getSimpleDao(): SimpleDao + + companion object { + + @Volatile + private var instance: MoviesRoomDatabase? = null + private val LOCK = Any() + + + operator fun invoke(context: Context) = instance ?: synchronized(LOCK) { + instance ?: buildDatabase(context).also { + instance = it + } + } + + private fun buildDatabase(context: Context) = + Room.databaseBuilder( + context.applicationContext, + MoviesRoomDatabase::class.java, + "MyDatabase.db" + ).build() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/h_mal/movielisttest/data/room/SimpleDao.kt b/app/src/main/java/com/example/h_mal/movielisttest/data/room/SimpleDao.kt new file mode 100644 index 0000000..d45a8a1 --- /dev/null +++ b/app/src/main/java/com/example/h_mal/movielisttest/data/room/SimpleDao.kt @@ -0,0 +1,32 @@ +package com.example.h_mal.movielisttest.data.room + +import androidx.lifecycle.LiveData +import androidx.room.* + +@Dao +interface SimpleDao { + + @Insert(onConflict = OnConflictStrategy.IGNORE) + fun saveAllItems(items: List) + + @Query("SELECT * FROM MovieEntity") + fun getAllItems(): LiveData> + + @Query("SELECT * FROM MovieEntity WHERE id = :id") + suspend fun getItem(id: Int): MovieEntity + + @Query("UPDATE MovieEntity SET favourites = :favourite WHERE id = :id") + fun setFavourite(id: Int, favourite: Boolean) + + @Query("DELETE FROM MovieEntity") + suspend fun deleteEntries() + + @Transaction + suspend fun updateFavourite(id: Int){ + val fav = getItem(id).favourites + setFavourite(id, !fav) + } + + @Delete + fun deleteEntry(movie: MovieEntity) +} \ No newline at end of file diff --git a/app/src/main/java/com/example/h_mal/movielisttest/ui/main/MainFragment.kt b/app/src/main/java/com/example/h_mal/movielisttest/ui/main/MainFragment.kt new file mode 100644 index 0000000..f5f6ff0 --- /dev/null +++ b/app/src/main/java/com/example/h_mal/movielisttest/ui/main/MainFragment.kt @@ -0,0 +1,80 @@ +package com.example.h_mal.movielisttest.ui.main + +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.fragment.app.Fragment +import androidx.fragment.app.viewModels +import androidx.lifecycle.Observer +import androidx.recyclerview.widget.SimpleItemAnimator +import com.example.h_mal.movielisttest.R +import com.example.h_mal.movielisttest.utils.* +import kotlinx.android.synthetic.main.empty_view_item.view.* +import kotlinx.android.synthetic.main.main_fragment.* +import org.kodein.di.KodeinAware +import org.kodein.di.android.x.kodein +import org.kodein.di.generic.instance + +class MainFragment : Fragment(), KodeinAware { + override val kodein by kodein() + private val factory by instance() + + private val viewModel by viewModels { factory } + + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, + savedInstanceState: Bundle?): View { + return inflater.inflate(R.layout.main_fragment, container, false) + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + + viewModel.operationState.observe(viewLifecycleOwner, stateObserver) + viewModel.operationError.observe(viewLifecycleOwner, errorObserver) + + val mAdapter = MoviesRecyclerViewAdapter( + favouriteClickListener = { + viewModel.setFavourite(it) + } + ) + mAdapter.setHasStableIds(true) + + + recycler_view.apply { + setHasFixedSize(true) + adapter = mAdapter + scrollBottomReachedListener{ + viewModel.loadMoreMovies() + } + } + + viewModel.moviesLiveData.observe(viewLifecycleOwner, Observer { + empty_layout.hide() + mAdapter.updateList(it) + }) + + empty_layout.refresh.setOnClickListener { + viewModel.loadMovies() + } + } + + // toggle visibility of progress spinner while async operations are taking place + private val stateObserver = Observer> { + when(it.getContentIfNotHandled()){ + true -> { + progress_circular.show() + } + false -> { + progress_circular.hide() + } + } + } + + + private val errorObserver = Observer> { + it.getContentIfNotHandled()?.let { message -> + requireContext().displayToast(message) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/h_mal/movielisttest/ui/main/MainViewModel.kt b/app/src/main/java/com/example/h_mal/movielisttest/ui/main/MainViewModel.kt new file mode 100644 index 0000000..a3cf95a --- /dev/null +++ b/app/src/main/java/com/example/h_mal/movielisttest/ui/main/MainViewModel.kt @@ -0,0 +1,87 @@ +package com.example.h_mal.movielisttest.ui.main + +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.Observer +import androidx.lifecycle.ViewModel +import com.example.h_mal.movielisttest.data.models.Movie +import com.example.h_mal.movielisttest.data.repository.Repository +import com.example.h_mal.movielisttest.data.room.MovieEntity +import com.example.h_mal.movielisttest.utils.Event +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch +import java.io.IOException + +class MainViewModel( + private val repository: Repository +) : ViewModel() { + + val moviesLiveData = MutableLiveData>() + + val operationState = MutableLiveData>() + val operationError = MutableLiveData>() + + init { + val observer = Observer> { + val list = it.map {entity -> Movie(entity) } + moviesLiveData.postValue(list) + } + repository.getMoviesFromDatabase().observeForever (observer) + + loadMovies() + } + + fun loadMovies(){ + CoroutineScope(Dispatchers.IO).launch { + operationState.postValue(Event(true)) + try { + val response = repository.getMoviesFromApi(1) + // null check response exists and contains list of users + response?.results?.let { + // save users to database + repository.saveMoviesToDatabase(it) + } + }catch (e: IOException){ + operationError.postValue(Event(e.message!!)) + }finally { + operationState.postValue(Event(false)) + } + } + } + + fun loadMoreMovies(){ + CoroutineScope(Dispatchers.IO).launch { + operationState.postValue(Event(true)) + try { + val page = repository.getCurrentPage() + + val response = repository.getMoviesFromApi(page) + // null check response exists and contains list of users + response?.results?.let { + // save users to database + repository.saveMoviesToDatabase(it) + // update current page + repository.updateCurrentPage() + } + }catch (e: IOException){ + operationError.postValue(Event(e.message!!)) + }finally { + operationState.postValue(Event(false)) + } + } + } + + fun setFavourite(id: Int){ + CoroutineScope(Dispatchers.IO).launch { + operationState.postValue(Event(true)) + try { + // Set favourite + repository.setFavourite(id) + }catch (e: IOException){ + operationError.postValue(Event(e.message!!)) + }finally { + operationState.postValue(Event(false)) + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/h_mal/movielisttest/ui/main/MainViewModelFactory.kt b/app/src/main/java/com/example/h_mal/movielisttest/ui/main/MainViewModelFactory.kt new file mode 100644 index 0000000..aed8827 --- /dev/null +++ b/app/src/main/java/com/example/h_mal/movielisttest/ui/main/MainViewModelFactory.kt @@ -0,0 +1,22 @@ +package com.example.h_mal.movielisttest.ui.main + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.ViewModelProvider +import com.example.h_mal.movielisttest.data.repository.Repository + +/** + * Viewmodel factory for [MainViewModel] + * @repository injected into MainViewModel + */ +class MainViewModelFactory( + private val repository: Repository +) : ViewModelProvider.Factory{ + + @Suppress("UNCHECKED_CAST") + override fun create(modelClass: Class): T { + if (modelClass.isAssignableFrom(MainViewModel::class.java)) { + return (MainViewModel(repository)) as T + } + throw IllegalArgumentException("Unknown ViewModel class") + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/h_mal/movielisttest/ui/main/MoviesRecyclerViewAdapter.kt b/app/src/main/java/com/example/h_mal/movielisttest/ui/main/MoviesRecyclerViewAdapter.kt new file mode 100644 index 0000000..548ceda --- /dev/null +++ b/app/src/main/java/com/example/h_mal/movielisttest/ui/main/MoviesRecyclerViewAdapter.kt @@ -0,0 +1,82 @@ +package com.example.h_mal.movielisttest.ui.main + +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.example.h_mal.movielisttest.R +import com.example.h_mal.movielisttest.data.models.Movie +import com.example.h_mal.movielisttest.utils.loadImage +import com.squareup.picasso.Picasso +import kotlinx.android.synthetic.main.item_layout.view.* + +/** + * Recycler view adapter to bind movies to a recycler view with + */ +class MoviesRecyclerViewAdapter( + val favouriteClickListener: (Int) -> Unit +) : RecyclerView.Adapter() { + + var list = mutableListOf() + + fun updateList(movies: List) { + list.clear() + list.addAll(movies) + notifyDataSetChanged() + } + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder { + val itemTwo = + LayoutInflater.from(parent.context).inflate(R.layout.item_layout, parent, false) + return ItemOne(itemTwo) + } + + override fun getItemCount(): Int { + return list.size + } + + override fun getItemId(position: Int): Long { + list[position].id?.let { + return it.toLong() + } + return super.getItemId(position) + } + + override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { + if (holder is ItemOne) { + holder.populateMovie(list[position]) + holder.favourite.setOnClickListener { + list[position].id?.let { id -> favouriteClickListener(id) } + } + } + } + + internal inner class ItemOne(itemView: View) : RecyclerView.ViewHolder(itemView) { + val title: TextView = itemView.title_tv + val description: TextView = itemView.desc_tv + val dateTv: TextView = itemView.date_tv + val favourite: ImageView = itemView.fav_btn + val cellImageView: ImageView = itemView.movie_iv + val voteTextView: TextView = itemView.vote_average_tv + + fun populateMovie(movie: Movie) { + title.text = movie.title + description.text = movie.overview + dateTv.text = movie.releaseDate + movie.favourites?.let { setFavourite(it) } + voteTextView.text = movie.voteAverage.toString() + + cellImageView.loadImage(movie.posterPath) + } + + private fun setFavourite(fav: Boolean) { + if (fav) { + favourite.setImageResource(android.R.drawable.btn_star_big_on) + } else { + favourite.setImageResource(android.R.drawable.btn_star_big_off) + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/h_mal/movielisttest/utils/Event.kt b/app/src/main/java/com/example/h_mal/movielisttest/utils/Event.kt new file mode 100644 index 0000000..3ef8890 --- /dev/null +++ b/app/src/main/java/com/example/h_mal/movielisttest/utils/Event.kt @@ -0,0 +1,24 @@ +package com.example.h_mal.movielisttest.utils + +/** + * Used with livedata to make observation lifecycle aware + * Display livedata response only once + */ +open class Event(private val content: T) { + + var hasBeenHandled = false + private set // Allow external read but not write + + /** + * Returns the content and prevents its use again. + */ + fun getContentIfNotHandled(): T? { + return if (hasBeenHandled) { + null + } else { + hasBeenHandled = true + content + } + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/example/h_mal/movielisttest/utils/ViewUtils.kt b/app/src/main/java/com/example/h_mal/movielisttest/utils/ViewUtils.kt new file mode 100644 index 0000000..061cd50 --- /dev/null +++ b/app/src/main/java/com/example/h_mal/movielisttest/utils/ViewUtils.kt @@ -0,0 +1,41 @@ +package com.example.h_mal.movielisttest.utils + +import android.content.Context +import android.view.View +import android.widget.ImageView +import android.widget.Toast +import androidx.recyclerview.widget.RecyclerView +import com.example.h_mal.movielisttest.R +import com.squareup.picasso.Picasso + +fun View.show() { + this.visibility = View.VISIBLE +} + +fun View.hide() { + this.visibility = View.GONE +} + +fun Context.displayToast(message: String) { + Toast.makeText(this, message, Toast.LENGTH_LONG).show() +} + + +fun ImageView.loadImage(url: String?){ + Picasso.get() + .load(url) + .fit() + .centerCrop() + .into(this) +} + +fun RecyclerView.scrollBottomReachedListener(bottomReached: () -> Unit){ + addOnScrollListener(object : RecyclerView.OnScrollListener() { + override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) { + super.onScrollStateChanged(recyclerView, newState) + if (!recyclerView.canScrollVertically(1) && newState == RecyclerView.SCROLL_STATE_IDLE) { + bottomReached() + } + } + }) +} \ No newline at end of file diff --git a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 0000000..2b068d1 --- /dev/null +++ b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_launcher_background.xml b/app/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000..07d5da9 --- /dev/null +++ b/app/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/mad_max_sample.jpg b/app/src/main/res/drawable/mad_max_sample.jpg new file mode 100644 index 0000000000000000000000000000000000000000..ba9ec3968525440e148be84f1dac59d7a319e1b4 GIT binary patch literal 84103 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 + + + + + + + + + + + +