Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 11 additions & 1 deletion app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ apply from: 'jacoco.gradle'
apply from: 'lint.gradle'
apply from: 'build-scripts.gradle'

apply plugin: 'kotlin-kapt'
apply plugin: 'dagger.hilt.android.plugin'

repositories {
mavenCentral()
maven { url 'https://maven.google.com' }
Expand Down Expand Up @@ -171,12 +174,13 @@ ext {
lottie_version = "4.2.0"
core_version = "1.6.0"
desugar_jdk_version = "1.1.5"
hilt_version = "2.38.1"

// Compose
activity_compose_version = "1.3.1"
constraintlayout_compose_version = "1.0.0-rc01"
viewmodel_compose_version = "1.0.0-alpha07"
}

jacoco {
toolVersion = "0.8.7"
}
Expand Down Expand Up @@ -208,6 +212,8 @@ dependencies {
implementation "com.squareup.retrofit2:retrofit:$retrofit_version"
implementation "com.squareup.retrofit2:converter-moshi:$retrofit_version"

implementation "com.squareup.retrofit2:converter-gson:$retrofit_version"
Comment thread
fedeturazzini marked this conversation as resolved.

// Http Logging Interceptor
implementation "com.squareup.okhttp3:okhttp:$ok_http_version"
implementation "com.squareup.okhttp3:logging-interceptor:$ok_http_version"
Expand Down Expand Up @@ -292,6 +298,10 @@ dependencies {
implementation "androidx.lifecycle:lifecycle-viewmodel-compose:$viewmodel_compose_version"
implementation "com.google.android.material:compose-theme-adapter:$compose_version"

// Hilt: Official Google Dependency Injection Library
implementation "com.google.dagger:hilt-android:$hilt_version"
kapt "com.google.dagger:hilt-android-compiler:$hilt_version"

// Test
// Unit testing framework
androidTestImplementation "com.android.support.test:rules:$test_rule_version"
Expand Down
11 changes: 7 additions & 4 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,14 @@
android:networkSecurityConfig="@xml/network_security_config"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.AndroidBase.Main">

android:theme="@style/Theme.AndroidBase.Main" >
<activity
android:name=".ui.HiltActivity"
android:exported="false" />
<!-- Animation Widget -->
<receiver android:name=".widgets.AnimationWidget"
android:exported="false">
<receiver
android:name=".widgets.AnimationWidget"
android:exported="false" >
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
package com.rocketinsights.android

import android.app.Application
import com.rocketinsights.android.di.initKoin
import androidx.viewbinding.BuildConfig
import com.rocketinsights.android.di.koin.initKoin
import com.rocketinsights.android.work.messages.MessagesUpdateScheduler
import dagger.hilt.android.HiltAndroidApp
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import org.koin.android.ext.android.inject
import timber.log.Timber

@HiltAndroidApp
class RocketApplication : Application() {

private val applicationScope = CoroutineScope(Dispatchers.Default)
Expand Down
19 changes: 19 additions & 0 deletions app/src/main/java/com/rocketinsights/android/di/hilt/AppModule.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.rocketinsights.android.di.hilt

import android.content.Context
import com.rocketinsights.android.RocketApplication
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.android.qualifiers.ApplicationContext
import dagger.hilt.components.SingletonComponent
import javax.inject.Singleton

@Module
@InstallIn(SingletonComponent::class)
object AppModule {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need a module just to provide the application context?

@Singleton
@Provides
fun provideApplication(@ApplicationContext app: Context): RocketApplication =
app as RocketApplication
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package com.rocketinsights.android.di.hilt

import com.google.gson.GsonBuilder
import com.rocketinsights.android.models.recipe_hilt.RecipeDtoMapper
import com.rocketinsights.android.network.hiltexample.RecipeService
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import okhttp3.Interceptor
import okhttp3.OkHttpClient
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
import javax.inject.Singleton

@Module
@InstallIn(SingletonComponent::class)
object HiltNetworkModule {

private var okHttpClient: OkHttpClient? = null

@Singleton
@Provides
fun providesRecipeMapper(): RecipeDtoMapper = RecipeDtoMapper()

@Singleton
@Provides
fun provideRecipeService(): RecipeService {
return Retrofit.Builder()
.baseUrl("https://food2fork.ca/api/recipe/")
.addConverterFactory(GsonConverterFactory.create(GsonBuilder().create()))
.client(buildClientHttp())
.build()
.create(RecipeService::class.java)
}

private fun buildClientHttp(): OkHttpClient? {
okHttpClient = OkHttpClient.Builder()
.addInterceptor(buildInterceptor())
.build()

return okHttpClient
}

private fun buildInterceptor() = Interceptor { chain ->
var request = chain.request()

request = request.newBuilder()
.addHeader(
"Authorization",
"Token 9c8b06d329136da358c2d00e76946b0111ce2c48"
)
.build()

chain.proceed(request = request)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package com.rocketinsights.android.di.hilt

import com.rocketinsights.android.models.recipe_hilt.RecipeDtoMapper
import com.rocketinsights.android.network.hiltexample.RecipeService
import com.rocketinsights.android.repos.RecipeRepository
import com.rocketinsights.android.repos.RecipeRepositoryImplementation
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import javax.inject.Singleton

@Module
@InstallIn(SingletonComponent::class)
object RepositoryModule {

@Singleton
@Provides
fun provideRecipeRepository(
recipeService: RecipeService,
recipeMapper: RecipeDtoMapper,
): RecipeRepository {
return RecipeRepositoryImplementation(
recipeService = recipeService,
mapper = recipeMapper
)
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.rocketinsights.android.di
package com.rocketinsights.android.di.koin

import android.app.Application
import android.app.NotificationManager
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.rocketinsights.android.models.recipe_hilt

data class Recipe(
val id: Int,
val title: String,
val publisher: String,
val featuredImage: String,
val rating: Int = 0,
val sourceUrl: String,
val ingredients: List<String>,
val dateAdded: String,
val dateUpdated: String
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.rocketinsights.android.models.recipe_hilt

import com.google.gson.annotations.SerializedName

data class RecipeDto(
var pk: Int,
var title: String,
var publisher: String,
@SerializedName("featured_image")
var featuredImage: String,
var rating: Int = 0,
@SerializedName("source_url")
var sourceUrl: String,
var ingredients: List<String> = emptyList(),
@SerializedName("date_added")
var dateAdded: String,
@SerializedName("date_updated")
var dateUpdated: String,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.rocketinsights.android.models.recipe_hilt

class RecipeDtoMapper {
fun mapToDomainModel(model: RecipeDto): Recipe {
return Recipe(
id = model.pk,
title = model.title,
featuredImage = model.featuredImage,
rating = model.rating,
publisher = model.publisher,
sourceUrl = model.sourceUrl,
ingredients = model.ingredients,
dateAdded = model.dateAdded,
dateUpdated = model.dateUpdated,
)
}

fun toDomainList(initial: List<RecipeDto>): List<Recipe> = initial.map { mapToDomainModel(it) }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.rocketinsights.android.network.hiltexample

import com.rocketinsights.android.models.recipe_hilt.RecipeDto

data class RecipeSearchResponse(
val count: Int,
val results: List<RecipeDto>,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.rocketinsights.android.network.hiltexample

import retrofit2.http.GET
import retrofit2.http.Query

interface RecipeService {

@GET("search")
suspend fun searchRecipe(
@Query("page") page: Int,
@Query("query") query: String
): RecipeSearchResponse
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.rocketinsights.android.repos

import com.rocketinsights.android.models.recipe_hilt.Recipe

interface RecipeRepository {
suspend fun search(page: Int, query: String): List<Recipe>?
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.rocketinsights.android.repos

import com.rocketinsights.android.models.recipe_hilt.Recipe
import com.rocketinsights.android.models.recipe_hilt.RecipeDtoMapper
import com.rocketinsights.android.network.hiltexample.RecipeService

class RecipeRepositoryImplementation(
private val recipeService: RecipeService,
private val mapper: RecipeDtoMapper,
) : RecipeRepository {

override suspend fun search(page: Int, query: String): List<Recipe> =
mapper.toDomainList(recipeService.searchRecipe(page = page, query = query).results)
}
22 changes: 22 additions & 0 deletions app/src/main/java/com/rocketinsights/android/ui/HiltActivity.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package com.rocketinsights.android.ui

import android.os.Bundle
import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatActivity
import com.rocketinsights.android.viewmodels.HiltListViewModel
import dagger.hilt.android.AndroidEntryPoint

@AndroidEntryPoint
class HiltActivity : AppCompatActivity() {

private val viewModel: HiltListViewModel by viewModels()

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)

// TODO: Show data with JetpackCompose in next PR
viewModel.liveRecipe.observe(this) { recipe ->
// do nothing for now
}
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.rocketinsights.android.ui

import android.content.Intent
import android.content.pm.PackageManager
import android.net.Uri
import android.os.Bundle
Expand Down Expand Up @@ -126,6 +127,11 @@ class MainFragment : BaseFragment(R.layout.fragment_main) {
setFadeThroughTransition()
item.onNavDestinationSelected(findNavController())
}
R.id.hilt_activity -> {
setFadeThroughTransition()
Intent(this.context, HiltActivity::class.java).also { startActivity(it) }
true
}
else -> super.onOptionsItemSelected(item)
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package com.rocketinsights.android.viewmodels

import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.rocketinsights.android.models.recipe_hilt.Recipe
import com.rocketinsights.android.repos.RecipeRepository
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.launch
import javax.inject.Inject

@HiltViewModel
class HiltListViewModel
@Inject
constructor(
private val repository: RecipeRepository
) : ViewModel() {

private val recipes: MutableLiveData<List<Recipe>> = MutableLiveData()
val liveRecipe: LiveData<List<Recipe>> = recipes

init {
viewModelScope.launch {
val result = repository.search(
page = 1,
query = "beef carrot potato onion"
)

result?.apply {
recipes.value = this
}
}
}
}
3 changes: 3 additions & 0 deletions app/src/main/res/menu/main_menu.xml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@
<item
android:id="@+id/contacts_fragment"
android:title="@string/contacts" />
<item
android:id="@+id/hilt_activity"
android:title="@string/hilt" />
<item
android:id="@+id/menu_login"
android:title="@string/login" />
Expand Down
3 changes: 3 additions & 0 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -109,4 +109,7 @@
<!-- Contacts -->
<string name="contacts">Contacts</string>
<string name="contacts_permission_not_granted">Read contacts permission not granted</string>

<!-- Hilt -->
<string name="hilt">Hilt example</string>
</resources>
Loading