Replace Koin with Dagger Hilt
This commit is contained in:
parent
bdacaaae34
commit
3f98551b9d
15 changed files with 102 additions and 70 deletions
|
@ -5,6 +5,8 @@ import java.io.FileNotFoundException
|
|||
plugins {
|
||||
id("com.android.application")
|
||||
id("kotlin-android")
|
||||
id("kotlin-kapt")
|
||||
id("dagger.hilt.android.plugin")
|
||||
}
|
||||
|
||||
val keystoreProperties = Properties()
|
||||
|
@ -64,7 +66,8 @@ android {
|
|||
dependencies {
|
||||
implementation(project(":piholeclient"))
|
||||
implementation(libs.bundles.coroutines)
|
||||
implementation("io.insert-koin:koin-androidx-viewmodel:${libs.versions.koin.get()}")
|
||||
implementation(libs.hilt.android.core)
|
||||
kapt(libs.hilt.android.kapt)
|
||||
implementation(libs.androidx.core)
|
||||
implementation(libs.androidx.appcompat)
|
||||
implementation(libs.material)
|
||||
|
|
|
@ -7,17 +7,20 @@ import androidx.lifecycle.MutableLiveData
|
|||
import androidx.lifecycle.ViewModel
|
||||
import com.wbrawner.piholeclient.PiHoleApiService
|
||||
import com.wbrawner.piholeclient.VersionResponse
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
import java.net.ConnectException
|
||||
import java.net.SocketTimeoutException
|
||||
import javax.inject.Inject
|
||||
|
||||
const val KEY_BASE_URL = "baseUrl"
|
||||
const val KEY_API_KEY = "apiKey"
|
||||
const val IP_MIN = 0
|
||||
const val IP_MAX = 255
|
||||
|
||||
class AddPiHelperViewModel(
|
||||
@HiltViewModel
|
||||
class AddPiHelperViewModel @Inject constructor(
|
||||
private val sharedPreferences: SharedPreferences,
|
||||
private val apiService: PiHoleApiService
|
||||
) : ViewModel() {
|
||||
|
|
|
@ -10,15 +10,17 @@ import android.view.animation.LinearInterpolator
|
|||
import android.view.animation.RotateAnimation
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.activityViewModels
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.navigation.fragment.FragmentNavigatorExtras
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import com.wbrawner.pihelper.databinding.FragmentAddPiHoleBinding
|
||||
import org.koin.android.ext.android.inject
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
|
||||
@AndroidEntryPoint
|
||||
class AddPiHoleFragment : Fragment() {
|
||||
|
||||
private val viewModel: AddPiHelperViewModel by inject()
|
||||
private val viewModel: AddPiHelperViewModel by activityViewModels()
|
||||
private var _binding: FragmentAddPiHoleBinding? = null
|
||||
private val binding get() = _binding!!
|
||||
|
||||
|
|
|
@ -13,13 +13,15 @@ import android.view.ViewGroup
|
|||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.activityViewModels
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import com.wbrawner.pihelper.MainActivity.Companion.ACTION_FORGET_PIHOLE
|
||||
import com.wbrawner.pihelper.databinding.FragmentInfoBinding
|
||||
import org.koin.android.ext.android.inject
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
|
||||
@AndroidEntryPoint
|
||||
class InfoFragment : Fragment() {
|
||||
private val viewModel: AddPiHelperViewModel by inject()
|
||||
private val viewModel: AddPiHelperViewModel by activityViewModels()
|
||||
private var _binding: FragmentInfoBinding? = null
|
||||
private val binding get() = _binding!!
|
||||
|
||||
|
|
|
@ -3,17 +3,20 @@ package com.wbrawner.pihelper
|
|||
import android.graphics.drawable.ColorDrawable
|
||||
import android.os.Bundle
|
||||
import android.widget.Toast
|
||||
import androidx.activity.viewModels
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.navigation.NavController
|
||||
import androidx.navigation.findNavController
|
||||
import com.wbrawner.pihelper.MainFragment.Companion.ACTION_DISABLE
|
||||
import com.wbrawner.pihelper.MainFragment.Companion.ACTION_ENABLE
|
||||
import com.wbrawner.pihelper.MainFragment.Companion.EXTRA_DURATION
|
||||
import com.wbrawner.pihelper.databinding.ActivityMainBinding
|
||||
import org.koin.android.ext.android.inject
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
|
||||
@AndroidEntryPoint
|
||||
class MainActivity : AppCompatActivity() {
|
||||
private val addPiHoleViewModel: AddPiHelperViewModel by inject()
|
||||
private val addPiHoleViewModel: AddPiHelperViewModel by viewModels()
|
||||
private val navController: NavController by lazy {
|
||||
findNavController(R.id.content_main)
|
||||
}
|
||||
|
@ -22,7 +25,14 @@ class MainActivity : AppCompatActivity() {
|
|||
super.onCreate(savedInstanceState)
|
||||
val binding = ActivityMainBinding.inflate(layoutInflater)
|
||||
setContentView(binding.root)
|
||||
window.setBackgroundDrawable(ColorDrawable(getColor(R.color.colorSurface)))
|
||||
window.setBackgroundDrawable(
|
||||
ColorDrawable(
|
||||
ContextCompat.getColor(
|
||||
this,
|
||||
R.color.colorSurface
|
||||
)
|
||||
)
|
||||
)
|
||||
val args = when (intent.action) {
|
||||
ACTION_ENABLE -> {
|
||||
if (addPiHoleViewModel.apiKey == null) {
|
||||
|
|
|
@ -16,16 +16,18 @@ import androidx.appcompat.app.AppCompatActivity
|
|||
import androidx.core.content.ContextCompat.getColor
|
||||
import androidx.core.text.set
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.activityViewModels
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import com.wbrawner.pihelper.databinding.DialogDisableCustomTimeBinding
|
||||
import com.wbrawner.pihelper.databinding.FragmentMainBinding
|
||||
import com.wbrawner.piholeclient.Status
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import kotlinx.coroutines.launch
|
||||
import org.koin.android.ext.android.inject
|
||||
|
||||
@AndroidEntryPoint
|
||||
class MainFragment : Fragment() {
|
||||
private val viewModel: PiHelperViewModel by inject()
|
||||
private val viewModel: PiHelperViewModel by activityViewModels()
|
||||
private var _binding: FragmentMainBinding? = null
|
||||
private val binding get() = _binding!!
|
||||
|
||||
|
|
|
@ -1,23 +1,7 @@
|
|||
package com.wbrawner.pihelper
|
||||
|
||||
import android.app.Application
|
||||
import android.content.Context
|
||||
import com.wbrawner.piholeclient.piHoleClientModule
|
||||
import org.koin.android.ext.koin.androidContext
|
||||
import org.koin.android.ext.koin.androidLogger
|
||||
import org.koin.core.context.startKoin
|
||||
import dagger.hilt.android.HiltAndroidApp
|
||||
|
||||
@Suppress("unused")
|
||||
class PiHelperApplication: Application() {
|
||||
override fun onCreate() {
|
||||
super.onCreate()
|
||||
startKoin{
|
||||
androidLogger()
|
||||
androidContext(this@PiHelperApplication)
|
||||
modules(listOf(
|
||||
piHoleClientModule,
|
||||
piHelperModule
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
@HiltAndroidApp
|
||||
class PiHelperApplication : Application()
|
|
@ -1,33 +1,36 @@
|
|||
package com.wbrawner.pihelper
|
||||
|
||||
import android.content.Context
|
||||
import android.content.SharedPreferences
|
||||
import androidx.security.crypto.EncryptedSharedPreferences
|
||||
import com.wbrawner.piholeclient.NAME_BASE_URL
|
||||
import org.koin.androidx.viewmodel.dsl.viewModel
|
||||
import org.koin.core.qualifier.named
|
||||
import org.koin.dsl.module
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
import dagger.hilt.InstallIn
|
||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||
import dagger.hilt.components.SingletonComponent
|
||||
import javax.inject.Named
|
||||
import javax.inject.Singleton
|
||||
|
||||
const val ENCRYPTED_SHARED_PREFS_FILE_NAME = "pihelper.prefs"
|
||||
|
||||
val piHelperModule = module {
|
||||
single {
|
||||
@Module
|
||||
@InstallIn(SingletonComponent::class)
|
||||
object PiHelperModule {
|
||||
@Provides
|
||||
@Singleton
|
||||
fun providesSharedPreferences(@ApplicationContext context: Context): SharedPreferences =
|
||||
EncryptedSharedPreferences.create(
|
||||
ENCRYPTED_SHARED_PREFS_FILE_NAME,
|
||||
"pihelper",
|
||||
get(),
|
||||
context,
|
||||
EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
|
||||
EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
|
||||
)
|
||||
}
|
||||
|
||||
viewModel {
|
||||
AddPiHelperViewModel(get(), get())
|
||||
}
|
||||
|
||||
viewModel {
|
||||
PiHelperViewModel(get())
|
||||
}
|
||||
|
||||
single(named(NAME_BASE_URL)) {
|
||||
get<EncryptedSharedPreferences>().getString(KEY_BASE_URL, "")
|
||||
}
|
||||
@Provides
|
||||
@Singleton
|
||||
@Named(NAME_BASE_URL)
|
||||
fun providesBaseUrl(sharedPreferences: SharedPreferences) = sharedPreferences
|
||||
.getString(KEY_BASE_URL, "")
|
||||
}
|
|
@ -5,11 +5,14 @@ import androidx.lifecycle.ViewModel
|
|||
import com.wbrawner.piholeclient.PiHoleApiService
|
||||
import com.wbrawner.piholeclient.Status
|
||||
import com.wbrawner.piholeclient.StatusProvider
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.isActive
|
||||
import javax.inject.Inject
|
||||
import kotlin.coroutines.coroutineContext
|
||||
|
||||
class PiHelperViewModel(
|
||||
@HiltViewModel
|
||||
class PiHelperViewModel @Inject constructor(
|
||||
private val apiService: PiHoleApiService
|
||||
) : ViewModel() {
|
||||
val status = MutableLiveData<Status>()
|
||||
|
|
|
@ -10,15 +10,17 @@ import android.view.animation.Animation
|
|||
import android.view.animation.LinearInterpolator
|
||||
import android.view.animation.RotateAnimation
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.activityViewModels
|
||||
import androidx.lifecycle.Observer
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import androidx.transition.TransitionInflater
|
||||
import com.wbrawner.pihelper.databinding.FragmentRetrieveApiKeyBinding
|
||||
import org.koin.android.ext.android.inject
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
|
||||
@AndroidEntryPoint
|
||||
class RetrieveApiKeyFragment : Fragment() {
|
||||
private val viewModel: AddPiHelperViewModel by inject()
|
||||
private val viewModel: AddPiHelperViewModel by activityViewModels()
|
||||
private var _binding: FragmentRetrieveApiKeyBinding? = null
|
||||
private val binding get() = _binding!!
|
||||
|
||||
|
@ -50,8 +52,9 @@ class RetrieveApiKeyFragment : Fragment() {
|
|||
viewModel.authenticateWithPassword(binding.password.text.toString())
|
||||
} catch (ignored: Exception) {
|
||||
Log.e("Pi-helper", "Failed to authenticate with password", ignored)
|
||||
binding.password.error = "Failed to authenticate with given password. Please verify " +
|
||||
"you've entered it correctly and try again."
|
||||
binding.password.error =
|
||||
"Failed to authenticate with given password. Please verify " +
|
||||
"you've entered it correctly and try again."
|
||||
showProgress(false)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@ import android.view.animation.LinearInterpolator
|
|||
import android.view.animation.RotateAnimation
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.activityViewModels
|
||||
import androidx.lifecycle.Observer
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.navigation.fragment.FragmentNavigatorExtras
|
||||
|
@ -22,15 +23,16 @@ import androidx.navigation.fragment.findNavController
|
|||
import androidx.transition.Transition
|
||||
import androidx.transition.TransitionInflater
|
||||
import com.wbrawner.pihelper.databinding.FragmentScanNetworkBinding
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.launch
|
||||
import org.koin.android.ext.android.inject
|
||||
import java.net.Inet4Address
|
||||
|
||||
@AndroidEntryPoint
|
||||
class ScanNetworkFragment : Fragment() {
|
||||
|
||||
private val viewModel: AddPiHelperViewModel by inject()
|
||||
private val viewModel: AddPiHelperViewModel by activityViewModels()
|
||||
private var _binding: FragmentScanNetworkBinding? = null
|
||||
private val binding get() = _binding!!
|
||||
|
||||
|
|
|
@ -3,9 +3,11 @@ buildscript {
|
|||
google()
|
||||
mavenCentral()
|
||||
}
|
||||
val hiltVersion by extra("2.36")
|
||||
val kotlinVersion by extra("1.4.32")
|
||||
dependencies {
|
||||
classpath("com.android.tools.build:gradle:7.0.0-beta03")
|
||||
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:${kotlinVersion}")
|
||||
classpath("com.google.dagger:hilt-android-gradle-plugin:$hiltVersion")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,13 +3,13 @@ androidx-core = "1.3.2"
|
|||
androidx-appcompat = "1.2.0"
|
||||
coroutines = "1.4.3"
|
||||
espresso = "3.3.0"
|
||||
koin = "2.2.3"
|
||||
hilt-android = "2.36"
|
||||
kotlin = "1.4.32"
|
||||
lifecycle = "2.2.0"
|
||||
material = "1.3.0"
|
||||
maxSdk = "30"
|
||||
moshi = "1.9.2"
|
||||
minSdk = "21"
|
||||
minSdk = "23"
|
||||
navigation = "2.3.2"
|
||||
okhttp = "4.2.2"
|
||||
versionCode = "1"
|
||||
|
@ -18,6 +18,8 @@ versionName = "1.0"
|
|||
[libraries]
|
||||
androidx-core = { module = "androidx.core:core-ktx", version.ref = "androidx-core" }
|
||||
androidx-appcompat = { module = "androidx.appcompat:appcompat", version.ref = "androidx-appcompat" }
|
||||
hilt-android-core = { module = "com.google.dagger:hilt-android", version.ref = "hilt-android" }
|
||||
hilt-android-kapt = { module = "com.google.dagger:hilt-compiler", version.ref = "hilt-android" }
|
||||
material = { module = "com.google.android.material:material", version.ref = "material" }
|
||||
moshi-core = { module = "com.squareup.moshi:moshi", version.ref = "moshi" }
|
||||
moshi-codegen = { module = "com.squareup.moshi:moshi-kotlin-codegen", version.ref = "moshi" }
|
||||
|
|
|
@ -2,6 +2,7 @@ plugins {
|
|||
id("com.android.library")
|
||||
id("kotlin-android")
|
||||
id("kotlin-kapt")
|
||||
id("dagger.hilt.android.plugin")
|
||||
}
|
||||
|
||||
android {
|
||||
|
@ -30,14 +31,15 @@ android {
|
|||
}
|
||||
|
||||
dependencies {
|
||||
implementation("io.insert-koin:koin-core:${libs.versions.koin.get()}")
|
||||
implementation("com.squareup.okhttp3:okhttp:${libs.versions.okhttp.get()}")
|
||||
api("com.squareup.okhttp3:okhttp:${libs.versions.okhttp.get()}")
|
||||
implementation("com.squareup.okhttp3:logging-interceptor:${libs.versions.okhttp.get()}")
|
||||
implementation(libs.androidx.core)
|
||||
implementation(libs.androidx.appcompat)
|
||||
implementation(libs.bundles.coroutines)
|
||||
implementation(libs.hilt.android.core)
|
||||
kapt(libs.hilt.android.kapt)
|
||||
implementation(libs.kotlin.reflect)
|
||||
implementation(libs.moshi.core)
|
||||
api(libs.moshi.core)
|
||||
kapt(libs.moshi.codegen)
|
||||
testImplementation(libs.junit)
|
||||
}
|
||||
|
|
|
@ -2,23 +2,31 @@ package com.wbrawner.piholeclient
|
|||
|
||||
import com.squareup.moshi.JsonReader
|
||||
import com.squareup.moshi.Moshi
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
import dagger.hilt.InstallIn
|
||||
import dagger.hilt.components.SingletonComponent
|
||||
import okhttp3.Cookie
|
||||
import okhttp3.CookieJar
|
||||
import okhttp3.HttpUrl
|
||||
import okhttp3.OkHttpClient
|
||||
import okhttp3.logging.HttpLoggingInterceptor
|
||||
import okio.Buffer
|
||||
import org.koin.dsl.module
|
||||
import java.util.concurrent.TimeUnit
|
||||
import javax.inject.Singleton
|
||||
|
||||
const val NAME_BASE_URL = "baseUrl"
|
||||
|
||||
val piHoleClientModule = module {
|
||||
single {
|
||||
Moshi.Builder().build()
|
||||
}
|
||||
@Module
|
||||
@InstallIn(SingletonComponent::class)
|
||||
object PiHoleClientModule {
|
||||
@Provides
|
||||
@Singleton
|
||||
fun providesMoshi(): Moshi = Moshi.Builder().build()
|
||||
|
||||
single {
|
||||
@Provides
|
||||
@Singleton
|
||||
fun providesOkHttpClient(): OkHttpClient {
|
||||
val client = OkHttpClient.Builder()
|
||||
.connectTimeout(500, TimeUnit.MILLISECONDS)
|
||||
.cookieJar(object : CookieJar {
|
||||
|
@ -53,10 +61,11 @@ val piHoleClientModule = module {
|
|||
}
|
||||
)
|
||||
}
|
||||
client.build()
|
||||
return client.build()
|
||||
}
|
||||
|
||||
single<PiHoleApiService> {
|
||||
OkHttpPiHoleApiService(get(), get())
|
||||
}
|
||||
@Provides
|
||||
@Singleton
|
||||
fun providesPiHoleApiService(okHttpClient: OkHttpClient, moshi: Moshi): PiHoleApiService =
|
||||
OkHttpPiHoleApiService(okHttpClient, moshi)
|
||||
}
|
Loading…
Reference in a new issue