Skip to content

Commit

Permalink
Replacing Dagger Hilt with Koin for Dependency injection.
Browse files Browse the repository at this point in the history
  • Loading branch information
Debanshu Datta committed Jun 24, 2022
1 parent 8824ff9 commit 9bad062
Show file tree
Hide file tree
Showing 14 changed files with 114 additions and 106 deletions.
11 changes: 4 additions & 7 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ plugins {
id 'kotlin-android'
id 'kotlinx-serialization'
id "kotlin-kapt"
id "dagger.hilt.android.plugin"
id 'com.google.android.libraries.mapsplatform.secrets-gradle-plugin'
id 'com.squareup.sqldelight'
}
Expand Down Expand Up @@ -68,6 +67,7 @@ dependencies {
debugImplementation "androidx.compose.ui:ui-tooling:$compose_version"
implementation "androidx.compose.runtime:runtime-livedata:$compose_version"
implementation "androidx.compose.material:material-icons-extended:$compose_version"
implementation "androidx.lifecycle:lifecycle-viewmodel-compose:2.4.1"

// Coroutines
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.2'
Expand All @@ -80,12 +80,9 @@ dependencies {
implementation "androidx.lifecycle:lifecycle-extensions:2.2.0"
implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.4.1"

// Dagger - Hilt
kapt "com.google.dagger:hilt-android-compiler:2.39"
implementation "androidx.hilt:hilt-lifecycle-viewmodel:1.0.0-alpha03"
kapt "androidx.hilt:hilt-compiler:1.0.0"
implementation 'com.google.dagger:hilt-android:2.39'
implementation "androidx.hilt:hilt-navigation-compose:1.0.0"
//Koin
implementation "io.insert-koin:koin-android:3.2.0-beta-1"
implementation "io.insert-koin:koin-androidx-compose:3.2.0-beta-1"

// Ktor Client
def ktor_version = '2.0.2'
Expand Down
91 changes: 30 additions & 61 deletions app/src/main/java/com/debanshu777/compose_github/di/AppModule.kt
Original file line number Diff line number Diff line change
@@ -1,84 +1,53 @@
package com.debanshu777.compose_github.di

import android.content.Context
import android.util.Log
import com.debanshu777.compose_github.GithubDatatbase
import com.debanshu777.compose_github.network.dataSource.GitHubViewModel
import com.debanshu777.compose_github.network.dataSource.MainRepository
import com.debanshu777.compose_github.network.dataSource.local.DeveloperDataSource
import com.debanshu777.compose_github.network.dataSource.local.DeveloperDataSourceImpl
import com.debanshu777.compose_github.network.dataSource.local.LocalRepository
import com.debanshu777.compose_github.network.dataSource.local.RepositoryDataSource
import com.debanshu777.compose_github.network.dataSource.local.RepositoryDataSourceImpl
import com.debanshu777.compose_github.network.dataSource.remote.RemoteRepository
import com.squareup.sqldelight.android.AndroidSqliteDriver
import com.squareup.sqldelight.db.SqlDriver
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.android.qualifiers.ApplicationContext
import dagger.hilt.components.SingletonComponent
import io.ktor.client.*
import io.ktor.client.engine.android.*
import io.ktor.client.plugins.*
import io.ktor.client.plugins.contentnegotiation.*
import io.ktor.client.plugins.logging.*
import io.ktor.client.request.*
import io.ktor.http.*
import io.ktor.serialization.kotlinx.json.*
import kotlinx.serialization.json.Json
import javax.inject.Singleton
import org.koin.android.ext.koin.androidContext
import org.koin.androidx.viewmodel.dsl.viewModel
import org.koin.dsl.module

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

@Provides
@Singleton
fun providesSqlDriver(@ApplicationContext context: Context): SqlDriver {
return AndroidSqliteDriver(
val appModule = module {
single<SqlDriver> {
AndroidSqliteDriver(
schema = GithubDatatbase.Schema,
context = context,
context = androidContext(),
name = "github.db"
)
}

@Provides
@Singleton
fun provideRepositoryDataSource(driver: SqlDriver): RepositoryDataSource {
return RepositoryDataSourceImpl(GithubDatatbase(driver))
single<RepositoryDataSource> {
RepositoryDataSourceImpl(GithubDatatbase(get()))
}

@Provides
@Singleton
fun provideDeveloperDataSource(driver: SqlDriver): DeveloperDataSource {
return DeveloperDataSourceImpl(GithubDatatbase(driver))
single<DeveloperDataSource> {
DeveloperDataSourceImpl(GithubDatatbase(get()))
}

@Provides
fun provideKtorAPIClient(): HttpClient {
val jsonProps = Json {
single {
Json {
encodeDefaults = true
ignoreUnknownKeys = true
isLenient = true
}
return HttpClient(Android) {
install(ContentNegotiation) {
json(jsonProps)
}
install(Logging) {
logger = object : Logger {
override fun log(message: String) {
Log.d("Network Message", "log: $message")
}
}
level = LogLevel.ALL
}
install(HttpTimeout) {
socketTimeoutMillis = 30_0000
requestTimeoutMillis = 30_0000
connectTimeoutMillis = 30_0000
}
defaultRequest {
contentType(ContentType.Application.Json)
accept(ContentType.Application.Json)
}
}
}
}
single {
RemoteRepository()
}
single {
LocalRepository(get(), get())
}
single {
MainRepository(get(), get())
}
viewModel {
GitHubViewModel(get())
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,11 @@ import com.debanshu777.compose_github.ui.feature_trending.state.DeveloperTrendin
import com.debanshu777.compose_github.ui.feature_trending.state.RepositoryTrendingState
import com.debanshu777.compose_github.utils.DurationType
import com.debanshu777.compose_github.utils.Resource
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.async
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.launch
import javax.inject.Inject

@HiltViewModel
class GitHubViewModel @Inject constructor(private val mainRepository: MainRepository) :
class GitHubViewModel constructor(private val mainRepository: MainRepository) :
ViewModel() {
private val _userDataState = MutableLiveData(ProfileState())
val userDataState: LiveData<ProfileState> = _userDataState
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,15 @@ import com.debanshu777.compose_github.utils.Resource
import composedb.githubDB.DeveloperFollow
import composedb.githubDB.RepositoryFollow
import kotlinx.coroutines.flow.Flow
import javax.inject.Inject

class MainRepository @Inject constructor(
class MainRepository constructor(
private val remoteRepository: RemoteRepository,
private val localRepository: LocalRepository
) {
suspend fun getRepositoryById(id: Long): RepositoryFollow? {
return localRepository.getRepositoryById(id)
}

suspend fun getDeveloperById(Id: Long): DeveloperFollow? {
return localRepository.getDeveloperById(Id)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,15 @@ package com.debanshu777.compose_github.network.dataSource.local
import composedb.githubDB.DeveloperFollow
import composedb.githubDB.RepositoryFollow
import kotlinx.coroutines.flow.Flow
import javax.inject.Inject

class LocalRepository @Inject constructor(
class LocalRepository constructor(
private val developerDataSourceImpl: DeveloperDataSource,
private val repositoryDataSourceImpl: RepositoryDataSource
) {
suspend fun getRepositoryById(id: Long): RepositoryFollow? {
return repositoryDataSourceImpl.getRepositoryById(id)
}

suspend fun getDeveloperById(Id: Long): DeveloperFollow? {
return developerDataSourceImpl.getDeveloperById(Id)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.debanshu777.compose_github.network.dataSource.remote

import android.util.Log
import com.debanshu777.compose_github.BuildConfig
import com.debanshu777.compose_github.network.model.GitHubSearchResponse
import com.debanshu777.compose_github.network.model.GitHubUserResponse
Expand All @@ -14,16 +15,20 @@ import com.debanshu777.compose_github.utils.Constant.USER_STATS_URL
import com.debanshu777.compose_github.utils.Resource
import io.ktor.client.*
import io.ktor.client.call.*
import io.ktor.client.engine.android.*
import io.ktor.client.plugins.*
import io.ktor.client.plugins.contentnegotiation.*
import io.ktor.client.plugins.logging.*
import io.ktor.client.request.*
import javax.inject.Inject
import javax.inject.Provider
import io.ktor.http.*
import io.ktor.serialization.kotlinx.json.*
import kotlinx.serialization.json.Json

class RemoteRepository @Inject constructor() {
@Inject lateinit var httpClient: Provider<HttpClient>
class RemoteRepository {
suspend fun getUserData(userId: String): Resource<GitHubUserResponse> {
return try {
Resource.Success(
data = httpClient.get().use {
data = getClient().use {
it.get("${GITHUB_BASE_URL}users/$userId").body()
}
)
Expand All @@ -35,7 +40,7 @@ class RemoteRepository @Inject constructor() {
suspend fun searchUser(searchText: String): Resource<GitHubSearchResponse> {
return try {
Resource.Success(
data = httpClient.get().use {
data = getClient().use {
it.get("${GITHUB_BASE_URL}search/users") {
parameter("q", searchText)
}.body()
Expand All @@ -49,7 +54,7 @@ class RemoteRepository @Inject constructor() {
suspend fun getTrendingRepository(timeline: String): Resource<List<TrendingRepositoryItem>> {
return try {
Resource.Success(
data = httpClient.get().use {
data = getClient().use {
it.get("${RAPID_BASE_API}repositories") {
parameter("since", timeline)
headers {
Expand All @@ -67,7 +72,7 @@ class RemoteRepository @Inject constructor() {
suspend fun getTrendingDeveloper(timeline: String): Resource<List<TrendingDeveloperItem>> {
return try {
Resource.Success(
data = httpClient.get().use {
data = getClient().use {
it.get("${RAPID_BASE_API}developers") {
parameter("since", timeline)
headers {
Expand All @@ -85,7 +90,7 @@ class RemoteRepository @Inject constructor() {
suspend fun getUserPinnedProject(username: String): Resource<List<PinnedUserProjectItem>> {
return try {
Resource.Success(
data = httpClient.get().use {
data = getClient().use {
it.get(PINNED_PROJECT_URL) {
parameter("username", username)
}
Expand All @@ -99,12 +104,41 @@ class RemoteRepository @Inject constructor() {
suspend fun getUserStats(username: String): Resource<UserStats> {
return try {
Resource.Success(
data = httpClient.get().use {
data = getClient().use {
it.get("${USER_STATS_URL}${username}")
}.body()
)
} catch (e: Exception) {
Resource.Error(message = e.message.toString())
}
}

private fun getClient(): HttpClient {
return HttpClient(Android) {
install(ContentNegotiation) {
json(Json {
encodeDefaults = true
ignoreUnknownKeys = true
isLenient = true
})
}
install(Logging) {
logger = object : Logger {
override fun log(message: String) {
Log.d("Network Message", "log: $message")
}
}
level = LogLevel.ALL
}
install(HttpTimeout) {
socketTimeoutMillis = 30_0000
requestTimeoutMillis = 30_0000
connectTimeoutMillis = 30_0000
}
defaultRequest {
contentType(ContentType.Application.Json)
accept(ContentType.Application.Json)
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ data class PinnedUserProjectItem(
@SerialName("description")
val description: String? = null, // Snapchat Clone with Jetpack Compose and Clean Architecture - Navigation Components, CamaraX, android-maps-compose, Exoplayer, Detekt, Coil, Gradle Secrets, Permission Handling.
@SerialName("forks")
val forks: Int?, // 0
val forks: String?, // 0
@SerialName("image")
val image: String?, // https://opengraph.githubassets.com/1/Debanshu777/Compose-Snapchat-Clone
@SerialName("language")
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,21 @@
package com.debanshu777.compose_github.ui

import android.app.Application
import dagger.hilt.android.HiltAndroidApp
import com.debanshu777.compose_github.di.appModule
import org.koin.android.ext.koin.androidContext
import org.koin.android.ext.koin.androidLogger
import org.koin.core.context.startKoin

@HiltAndroidApp
class BaseApplication : Application()

class BaseApplication : Application() {
override fun onCreate() {
super.onCreate()
startKoin {
androidLogger()
androidContext(this@BaseApplication)
modules(
appModule
)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,17 @@ import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.hilt.navigation.compose.hiltViewModel
import com.debanshu777.compose_github.network.dataSource.GitHubViewModel
import com.debanshu777.compose_github.ui.base.MainScreen
import com.debanshu777.compose_github.ui.theme.ComposeGithubTheme
import dagger.hilt.android.AndroidEntryPoint
import org.koin.androidx.viewmodel.ext.android.getViewModel

@AndroidEntryPoint
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
ComposeGithubTheme {
val viewModel: GitHubViewModel = hiltViewModel()
val viewModel: GitHubViewModel = getViewModel()
// A surface container using the 'background' color from the theme
Surface(color = MaterialTheme.colorScheme.background) {
MainScreen(viewModel)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,16 @@ import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.navigation.NavController
import com.debanshu777.compose_github.network.dataSource.GitHubViewModel
import com.debanshu777.compose_github.ui.base.components.tabHandler.TabHandler
import com.google.accompanist.pager.ExperimentalPagerApi
import com.google.accompanist.pager.rememberPagerState
import org.koin.androidx.compose.getViewModel

@OptIn(ExperimentalPagerApi::class)
@Composable
fun FollowScreen(navController: NavController, viewModel: GitHubViewModel = hiltViewModel()) {
fun FollowScreen(navController: NavController, viewModel: GitHubViewModel = getViewModel()) {
val developerFollowList by viewModel.developerList.collectAsState(emptyList())
val repositoryFollowList by viewModel.repositoryList.collectAsState(emptyList())
val pagerState = rememberPagerState(0)
Expand Down
Loading

0 comments on commit 9bad062

Please sign in to comment.