adding DepedencyInjnection with HILT
This commit is contained in:
@@ -2,6 +2,12 @@ plugins {
|
|||||||
id("com.android.application")
|
id("com.android.application")
|
||||||
id("org.jetbrains.kotlin.android")
|
id("org.jetbrains.kotlin.android")
|
||||||
id("androidx.navigation.safeargs.kotlin")
|
id("androidx.navigation.safeargs.kotlin")
|
||||||
|
id("kotlin-kapt")
|
||||||
|
id("com.google.dagger.hilt.android")
|
||||||
|
}
|
||||||
|
|
||||||
|
kapt {
|
||||||
|
correctErrorTypes = true
|
||||||
}
|
}
|
||||||
|
|
||||||
android {
|
android {
|
||||||
@@ -11,6 +17,12 @@ android {
|
|||||||
lint {
|
lint {
|
||||||
abortOnError = false
|
abortOnError = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
packaging {
|
||||||
|
resources {
|
||||||
|
excludes += "/META-INF/{AL2.0,LGPL2.1}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
applicationId = "com.mattintech.lchat"
|
applicationId = "com.mattintech.lchat"
|
||||||
@@ -50,6 +62,7 @@ android {
|
|||||||
}
|
}
|
||||||
buildFeatures {
|
buildFeatures {
|
||||||
viewBinding = true
|
viewBinding = true
|
||||||
|
buildConfig = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -66,6 +79,10 @@ dependencies {
|
|||||||
implementation("androidx.navigation:navigation-fragment-ktx:2.7.6")
|
implementation("androidx.navigation:navigation-fragment-ktx:2.7.6")
|
||||||
implementation("androidx.navigation:navigation-ui-ktx:2.7.6")
|
implementation("androidx.navigation:navigation-ui-ktx:2.7.6")
|
||||||
|
|
||||||
|
// Hilt dependencies
|
||||||
|
implementation("com.google.dagger:hilt-android:2.50")
|
||||||
|
kapt("com.google.dagger:hilt-compiler:2.50")
|
||||||
|
|
||||||
testImplementation("junit:junit:4.13.2")
|
testImplementation("junit:junit:4.13.2")
|
||||||
androidTestImplementation("androidx.test.ext:junit:1.1.5")
|
androidTestImplementation("androidx.test.ext:junit:1.1.5")
|
||||||
androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1")
|
androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1")
|
||||||
|
|||||||
15
app/proguard-rules.pro
vendored
15
app/proguard-rules.pro
vendored
@@ -11,4 +11,17 @@
|
|||||||
|
|
||||||
# If you keep the line number information, uncomment this to
|
# If you keep the line number information, uncomment this to
|
||||||
# hide the original source file name.
|
# hide the original source file name.
|
||||||
#-renamesourcefileattribute SourceFile
|
#-renamesourcefileattribute SourceFile
|
||||||
|
|
||||||
|
# Keep Application class
|
||||||
|
-keep class com.mattintech.lchat.LChatApplication { *; }
|
||||||
|
|
||||||
|
# Hilt rules
|
||||||
|
-keep class dagger.hilt.** { *; }
|
||||||
|
-keep class javax.inject.** { *; }
|
||||||
|
-keep class * extends dagger.hilt.android.internal.managers.ViewComponentManager { *; }
|
||||||
|
|
||||||
|
# Keep all @HiltAndroidApp, @AndroidEntryPoint, @HiltViewModel annotated classes
|
||||||
|
-keep @dagger.hilt.android.HiltAndroidApp class * { *; }
|
||||||
|
-keep @dagger.hilt.android.AndroidEntryPoint class * { *; }
|
||||||
|
-keep @dagger.hilt.android.lifecycle.HiltViewModel class * { *; }
|
||||||
@@ -15,6 +15,7 @@
|
|||||||
<uses-feature android:name="android.hardware.wifi.aware" android:required="true" />
|
<uses-feature android:name="android.hardware.wifi.aware" android:required="true" />
|
||||||
|
|
||||||
<application
|
<application
|
||||||
|
android:name=".LChatApplication"
|
||||||
android:allowBackup="true"
|
android:allowBackup="true"
|
||||||
android:dataExtractionRules="@xml/data_extraction_rules"
|
android:dataExtractionRules="@xml/data_extraction_rules"
|
||||||
android:fullBackupContent="@xml/backup_rules"
|
android:fullBackupContent="@xml/backup_rules"
|
||||||
|
|||||||
11
app/src/main/java/com/mattintech/lchat/LChatApplication.kt
Normal file
11
app/src/main/java/com/mattintech/lchat/LChatApplication.kt
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
package com.mattintech.lchat
|
||||||
|
|
||||||
|
import android.app.Application
|
||||||
|
import dagger.hilt.android.HiltAndroidApp
|
||||||
|
|
||||||
|
@HiltAndroidApp
|
||||||
|
class LChatApplication : Application() {
|
||||||
|
override fun onCreate() {
|
||||||
|
super.onCreate()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -11,7 +11,9 @@ import androidx.core.content.ContextCompat
|
|||||||
import com.google.android.material.snackbar.Snackbar
|
import com.google.android.material.snackbar.Snackbar
|
||||||
import com.mattintech.lchat.databinding.ActivityMainBinding
|
import com.mattintech.lchat.databinding.ActivityMainBinding
|
||||||
import com.mattintech.lchat.utils.LOG_PREFIX
|
import com.mattintech.lchat.utils.LOG_PREFIX
|
||||||
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
|
|
||||||
|
@AndroidEntryPoint
|
||||||
class MainActivity : AppCompatActivity() {
|
class MainActivity : AppCompatActivity() {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|||||||
23
app/src/main/java/com/mattintech/lchat/di/AppModule.kt
Normal file
23
app/src/main/java/com/mattintech/lchat/di/AppModule.kt
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
package com.mattintech.lchat.di
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import com.mattintech.lchat.network.WifiAwareManager
|
||||||
|
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 {
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
@Singleton
|
||||||
|
fun provideWifiAwareManager(
|
||||||
|
@ApplicationContext context: Context
|
||||||
|
): WifiAwareManager {
|
||||||
|
return WifiAwareManager(context)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,24 +3,19 @@ package com.mattintech.lchat.repository
|
|||||||
import android.content.Context
|
import android.content.Context
|
||||||
import com.mattintech.lchat.data.Message
|
import com.mattintech.lchat.data.Message
|
||||||
import com.mattintech.lchat.network.WifiAwareManager
|
import com.mattintech.lchat.network.WifiAwareManager
|
||||||
|
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||||
import kotlinx.coroutines.*
|
import kotlinx.coroutines.*
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import kotlinx.coroutines.flow.StateFlow
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
import kotlinx.coroutines.flow.asStateFlow
|
import kotlinx.coroutines.flow.asStateFlow
|
||||||
import java.util.UUID
|
import java.util.UUID
|
||||||
|
import javax.inject.Inject
|
||||||
|
import javax.inject.Singleton
|
||||||
|
|
||||||
class ChatRepository private constructor(context: Context) {
|
@Singleton
|
||||||
|
class ChatRepository @Inject constructor(
|
||||||
companion object {
|
@ApplicationContext private val context: Context
|
||||||
@Volatile
|
) {
|
||||||
private var INSTANCE: ChatRepository? = null
|
|
||||||
|
|
||||||
fun getInstance(context: Context): ChatRepository {
|
|
||||||
return INSTANCE ?: synchronized(this) {
|
|
||||||
INSTANCE ?: ChatRepository(context.applicationContext).also { INSTANCE = it }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private val wifiAwareManager = WifiAwareManager(context)
|
private val wifiAwareManager = WifiAwareManager(context)
|
||||||
|
|
||||||
@@ -140,7 +135,7 @@ class ChatRepository private constructor(context: Context) {
|
|||||||
|
|
||||||
private fun startConnectionMonitoring() {
|
private fun startConnectionMonitoring() {
|
||||||
connectionCheckJob?.cancel()
|
connectionCheckJob?.cancel()
|
||||||
connectionCheckJob = GlobalScope.launch {
|
connectionCheckJob = CoroutineScope(Dispatchers.IO).launch {
|
||||||
while (isActive) {
|
while (isActive) {
|
||||||
delay(5000) // Check every 5 seconds
|
delay(5000) // Check every 5 seconds
|
||||||
val timeSinceLastActivity = System.currentTimeMillis() - lastActivityTime
|
val timeSinceLastActivity = System.currentTimeMillis() - lastActivityTime
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import android.view.LayoutInflater
|
|||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import androidx.lifecycle.ViewModelProvider
|
import androidx.fragment.app.viewModels
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
import androidx.navigation.fragment.navArgs
|
import androidx.navigation.fragment.navArgs
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
@@ -17,9 +17,10 @@ import com.mattintech.lchat.repository.ChatRepository
|
|||||||
import com.mattintech.lchat.ui.adapters.MessageAdapter
|
import com.mattintech.lchat.ui.adapters.MessageAdapter
|
||||||
import com.mattintech.lchat.utils.LOG_PREFIX
|
import com.mattintech.lchat.utils.LOG_PREFIX
|
||||||
import com.mattintech.lchat.viewmodel.ChatViewModel
|
import com.mattintech.lchat.viewmodel.ChatViewModel
|
||||||
import com.mattintech.lchat.viewmodel.ViewModelFactory
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
|
@AndroidEntryPoint
|
||||||
class ChatFragment : Fragment() {
|
class ChatFragment : Fragment() {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
@@ -30,7 +31,7 @@ class ChatFragment : Fragment() {
|
|||||||
private val binding get() = _binding!!
|
private val binding get() = _binding!!
|
||||||
|
|
||||||
private val args: ChatFragmentArgs by navArgs()
|
private val args: ChatFragmentArgs by navArgs()
|
||||||
private lateinit var viewModel: ChatViewModel
|
private val viewModel: ChatViewModel by viewModels()
|
||||||
private lateinit var messageAdapter: MessageAdapter
|
private lateinit var messageAdapter: MessageAdapter
|
||||||
|
|
||||||
override fun onCreateView(
|
override fun onCreateView(
|
||||||
@@ -47,8 +48,6 @@ class ChatFragment : Fragment() {
|
|||||||
super.onViewCreated(view, savedInstanceState)
|
super.onViewCreated(view, savedInstanceState)
|
||||||
Log.d(TAG, "onViewCreated - room: ${args.roomName}, user: ${args.userName}, isHost: ${args.isHost}")
|
Log.d(TAG, "onViewCreated - room: ${args.roomName}, user: ${args.userName}, isHost: ${args.isHost}")
|
||||||
|
|
||||||
val factory = ViewModelFactory(requireContext())
|
|
||||||
viewModel = ViewModelProvider(this, factory)[ChatViewModel::class.java]
|
|
||||||
viewModel.initialize(args.roomName, args.userName, args.isHost)
|
viewModel.initialize(args.roomName, args.userName, args.isHost)
|
||||||
|
|
||||||
setupUI()
|
setupUI()
|
||||||
|
|||||||
@@ -7,16 +7,17 @@ import android.view.View
|
|||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import androidx.lifecycle.ViewModelProvider
|
import androidx.fragment.app.viewModels
|
||||||
import androidx.navigation.fragment.findNavController
|
import androidx.navigation.fragment.findNavController
|
||||||
import com.mattintech.lchat.R
|
import com.mattintech.lchat.R
|
||||||
import com.mattintech.lchat.databinding.FragmentLobbyBinding
|
import com.mattintech.lchat.databinding.FragmentLobbyBinding
|
||||||
import com.mattintech.lchat.viewmodel.LobbyEvent
|
import com.mattintech.lchat.viewmodel.LobbyEvent
|
||||||
import com.mattintech.lchat.viewmodel.LobbyState
|
import com.mattintech.lchat.viewmodel.LobbyState
|
||||||
import com.mattintech.lchat.viewmodel.LobbyViewModel
|
import com.mattintech.lchat.viewmodel.LobbyViewModel
|
||||||
import com.mattintech.lchat.viewmodel.ViewModelFactory
|
|
||||||
import com.mattintech.lchat.utils.LOG_PREFIX
|
import com.mattintech.lchat.utils.LOG_PREFIX
|
||||||
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
|
|
||||||
|
@AndroidEntryPoint
|
||||||
class LobbyFragment : Fragment() {
|
class LobbyFragment : Fragment() {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
@@ -26,7 +27,7 @@ class LobbyFragment : Fragment() {
|
|||||||
private var _binding: FragmentLobbyBinding? = null
|
private var _binding: FragmentLobbyBinding? = null
|
||||||
private val binding get() = _binding!!
|
private val binding get() = _binding!!
|
||||||
|
|
||||||
private lateinit var viewModel: LobbyViewModel
|
private val viewModel: LobbyViewModel by viewModels()
|
||||||
|
|
||||||
override fun onCreateView(
|
override fun onCreateView(
|
||||||
inflater: LayoutInflater,
|
inflater: LayoutInflater,
|
||||||
@@ -42,9 +43,6 @@ class LobbyFragment : Fragment() {
|
|||||||
super.onViewCreated(view, savedInstanceState)
|
super.onViewCreated(view, savedInstanceState)
|
||||||
Log.d(TAG, "onViewCreated")
|
Log.d(TAG, "onViewCreated")
|
||||||
|
|
||||||
val factory = ViewModelFactory(requireContext())
|
|
||||||
viewModel = ViewModelProvider(this, factory)[LobbyViewModel::class.java]
|
|
||||||
|
|
||||||
setupUI()
|
setupUI()
|
||||||
observeViewModel()
|
observeViewModel()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,11 +6,13 @@ import androidx.lifecycle.ViewModel
|
|||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
import com.mattintech.lchat.data.Message
|
import com.mattintech.lchat.data.Message
|
||||||
import com.mattintech.lchat.repository.ChatRepository
|
import com.mattintech.lchat.repository.ChatRepository
|
||||||
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
import kotlinx.coroutines.flow.SharingStarted
|
import kotlinx.coroutines.flow.SharingStarted
|
||||||
import kotlinx.coroutines.flow.StateFlow
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
import kotlinx.coroutines.flow.stateIn
|
import kotlinx.coroutines.flow.stateIn
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import java.util.UUID
|
import java.util.UUID
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
sealed class ChatState {
|
sealed class ChatState {
|
||||||
object Connected : ChatState()
|
object Connected : ChatState()
|
||||||
@@ -18,7 +20,8 @@ sealed class ChatState {
|
|||||||
data class Error(val message: String) : ChatState()
|
data class Error(val message: String) : ChatState()
|
||||||
}
|
}
|
||||||
|
|
||||||
class ChatViewModel(
|
@HiltViewModel
|
||||||
|
class ChatViewModel @Inject constructor(
|
||||||
private val chatRepository: ChatRepository
|
private val chatRepository: ChatRepository
|
||||||
) : ViewModel() {
|
) : ViewModel() {
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,9 @@ import androidx.lifecycle.MutableLiveData
|
|||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
import com.mattintech.lchat.repository.ChatRepository
|
import com.mattintech.lchat.repository.ChatRepository
|
||||||
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
sealed class LobbyState {
|
sealed class LobbyState {
|
||||||
object Idle : LobbyState()
|
object Idle : LobbyState()
|
||||||
@@ -23,7 +25,8 @@ sealed class LobbyEvent {
|
|||||||
data class ShowError(val message: String) : LobbyEvent()
|
data class ShowError(val message: String) : LobbyEvent()
|
||||||
}
|
}
|
||||||
|
|
||||||
class LobbyViewModel(
|
@HiltViewModel
|
||||||
|
class LobbyViewModel @Inject constructor(
|
||||||
private val chatRepository: ChatRepository
|
private val chatRepository: ChatRepository
|
||||||
) : ViewModel() {
|
) : ViewModel() {
|
||||||
|
|
||||||
|
|||||||
@@ -1,24 +0,0 @@
|
|||||||
package com.mattintech.lchat.viewmodel
|
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import androidx.lifecycle.ViewModel
|
|
||||||
import androidx.lifecycle.ViewModelProvider
|
|
||||||
import com.mattintech.lchat.repository.ChatRepository
|
|
||||||
|
|
||||||
class ViewModelFactory(private val context: Context) : ViewModelProvider.Factory {
|
|
||||||
|
|
||||||
private val chatRepository by lazy { ChatRepository.getInstance(context) }
|
|
||||||
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
|
||||||
override fun <T : ViewModel> create(modelClass: Class<T>): T {
|
|
||||||
return when {
|
|
||||||
modelClass.isAssignableFrom(LobbyViewModel::class.java) -> {
|
|
||||||
LobbyViewModel(chatRepository) as T
|
|
||||||
}
|
|
||||||
modelClass.isAssignableFrom(ChatViewModel::class.java) -> {
|
|
||||||
ChatViewModel(chatRepository) as T
|
|
||||||
}
|
|
||||||
else -> throw IllegalArgumentException("Unknown ViewModel class: ${modelClass.name}")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -11,5 +11,6 @@ buildscript {
|
|||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
id("com.android.application") version "8.9.1" apply false
|
id("com.android.application") version "8.9.1" apply false
|
||||||
id("org.jetbrains.kotlin.android") version "1.9.0" apply false
|
id("org.jetbrains.kotlin.android") version "1.9.22" apply false
|
||||||
|
id("com.google.dagger.hilt.android") version "2.50" apply false
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,12 @@
|
|||||||
# Project-wide Gradle settings.
|
# Project-wide Gradle settings.
|
||||||
org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
|
org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8 --add-exports=jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED --add-exports=jdk.compiler/com.sun.tools.javac.model=ALL-UNNAMED --add-exports=jdk.compiler/com.sun.tools.javac.processing=ALL-UNNAMED --add-exports=jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED --add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED --add-exports=jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED --add-exports=jdk.compiler/com.sun.tools.javac.comp=ALL-UNNAMED
|
||||||
android.useAndroidX=true
|
android.useAndroidX=true
|
||||||
android.nonTransitiveRClass=true
|
android.nonTransitiveRClass=true
|
||||||
android.defaults.buildfeatures.buildconfig=true
|
android.nonFinalResIds=false
|
||||||
android.nonFinalResIds=false
|
|
||||||
|
# Kapt configuration for better performance
|
||||||
|
kapt.use.worker.api=true
|
||||||
|
kapt.incremental.apt=true
|
||||||
|
|
||||||
|
# Hilt configuration
|
||||||
|
dagger.hilt.android.internal.disableAndroidSuperclassValidation=true
|
||||||
Reference in New Issue
Block a user