Refactor HiltViewModels ApplicationContext (#446)

* Simplified ViewModels

Signed-off-by: Arnau Mora <arnyminerz@proton.me>

* Fixed injection

Signed-off-by: Arnau Mora <arnyminerz@proton.me>

* Fixed settings injection

Signed-off-by: Arnau Mora <arnyminerz@proton.me>

* Added missing import

Signed-off-by: Arnau Mora <arnyminerz@proton.me>

* Fixed application

Signed-off-by: Arnau Mora <arnyminerz@proton.me>

* Fixed constructors and got rid of utils

Signed-off-by: Arnau Mora <arnyminerz@proton.me>

* Optimized imports

Signed-off-by: Arnau Mora <arnyminerz@proton.me>

* Added missing annotation

Signed-off-by: Arnau Mora <arnyminerz@proton.me>

---------

Signed-off-by: Arnau Mora <arnyminerz@proton.me>
This commit is contained in:
Arnau Mora 2023-10-19 17:36:11 +02:00 committed by GitHub
parent f8330e8f52
commit fe679da03b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 53 additions and 38 deletions

View file

@ -5,7 +5,7 @@
package at.bitfire.davdroid.ui.webdav
import android.security.NetworkSecurityPolicy
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.core.app.ApplicationProvider
import at.bitfire.davdroid.db.AppDatabase
import at.bitfire.davdroid.db.WebDavMount
import dagger.hilt.android.testing.HiltAndroidRule
@ -34,7 +34,7 @@ class AddWebdavMountActivityTest {
fun setUp() {
hiltRule.inject()
model = spyk(AddWebdavMountActivity.Model(InstrumentationRegistry.getInstrumentation().targetContext, db))
model = spyk(AddWebdavMountActivity.Model(ApplicationProvider.getApplicationContext(), db))
Assume.assumeTrue(NetworkSecurityPolicy.getInstance().isCleartextTrafficPermitted)
}

View file

@ -4,6 +4,7 @@
package at.bitfire.davdroid.ui
import android.app.Application
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
@ -16,8 +17,8 @@ import androidx.annotation.AnyThread
import androidx.databinding.ObservableBoolean
import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import at.bitfire.davdroid.BuildConfig
import at.bitfire.davdroid.PackageChangedReceiver
import at.bitfire.davdroid.R
@ -28,7 +29,6 @@ import at.bitfire.ical4android.TaskProvider.ProviderName
import com.google.android.material.snackbar.Snackbar
import dagger.hilt.android.AndroidEntryPoint
import dagger.hilt.android.lifecycle.HiltViewModel
import dagger.hilt.android.qualifiers.ApplicationContext
import javax.inject.Inject
@AndroidEntryPoint
@ -102,9 +102,9 @@ class TasksFragment: Fragment() {
@HiltViewModel
class Model @Inject constructor(
@ApplicationContext val context: Context,
application: Application,
val settings: SettingsManager
) : ViewModel(), SettingsManager.OnChangeListener {
) : AndroidViewModel(application), SettingsManager.OnChangeListener {
companion object {
@ -117,6 +117,8 @@ class TasksFragment: Fragment() {
}
val context: Context get() = getApplication()
val currentProvider = MutableLiveData<ProviderName>()
val openTasksInstalled = MutableLiveData<Boolean>()
val openTasksRequested = MutableLiveData<Boolean>()

View file

@ -5,7 +5,7 @@
package at.bitfire.davdroid.ui.account
import android.accounts.Account
import android.content.Context
import android.app.Application
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
@ -15,20 +15,19 @@ import androidx.fragment.app.viewModels
import androidx.lifecycle.*
import at.bitfire.dav4jvm.DavResource
import at.bitfire.dav4jvm.XmlUtils
import at.bitfire.davdroid.util.DavUtils
import at.bitfire.davdroid.network.HttpClient
import at.bitfire.davdroid.R
import at.bitfire.davdroid.db.AppDatabase
import at.bitfire.davdroid.db.Collection
import at.bitfire.davdroid.log.Logger
import at.bitfire.davdroid.network.HttpClient
import at.bitfire.davdroid.servicedetection.RefreshCollectionsWorker
import at.bitfire.davdroid.settings.AccountSettings
import at.bitfire.davdroid.ui.ExceptionInfoFragment
import at.bitfire.davdroid.util.DavUtils
import dagger.assisted.Assisted
import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
import dagger.hilt.android.AndroidEntryPoint
import dagger.hilt.android.qualifiers.ApplicationContext
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.NonCancellable
import kotlinx.coroutines.launch
@ -117,12 +116,12 @@ class CreateCollectionFragment: DialogFragment() {
class Model @AssistedInject constructor(
@ApplicationContext val context: Context,
application: Application,
val db: AppDatabase,
@Assisted val account: Account,
@Assisted val serviceType: String,
@Assisted val collection: Collection
): ViewModel() {
): AndroidViewModel(application) {
@AssistedFactory
interface Factory {
@ -133,7 +132,7 @@ class CreateCollectionFragment: DialogFragment() {
fun createCollection(): LiveData<Exception> {
viewModelScope.launch(Dispatchers.IO + NonCancellable) {
HttpClient.Builder(context, AccountSettings(context, account))
HttpClient.Builder(getApplication(), AccountSettings(getApplication(), account))
.setForeground(true)
.build().use { httpClient ->
try {
@ -148,7 +147,7 @@ class CreateCollectionFragment: DialogFragment() {
db.collectionDao().insert(collection)
// trigger service detection (because the collection may have other properties than the ones we have inserted)
RefreshCollectionsWorker.refreshCollections(context, service.id)
RefreshCollectionsWorker.refreshCollections(getApplication(), service.id)
}
// post success

View file

@ -5,7 +5,7 @@
package at.bitfire.davdroid.ui.account
import android.accounts.Account
import android.content.Context
import android.app.Application
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
@ -14,17 +14,16 @@ import androidx.fragment.app.DialogFragment
import androidx.fragment.app.viewModels
import androidx.lifecycle.*
import at.bitfire.dav4jvm.DavResource
import at.bitfire.davdroid.network.HttpClient
import at.bitfire.davdroid.databinding.DeleteCollectionBinding
import at.bitfire.davdroid.db.AppDatabase
import at.bitfire.davdroid.db.Collection
import at.bitfire.davdroid.network.HttpClient
import at.bitfire.davdroid.settings.AccountSettings
import at.bitfire.davdroid.ui.ExceptionInfoFragment
import dagger.assisted.Assisted
import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
import dagger.hilt.android.AndroidEntryPoint
import dagger.hilt.android.qualifiers.ApplicationContext
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.NonCancellable
import kotlinx.coroutines.launch
@ -88,11 +87,11 @@ class DeleteCollectionFragment: DialogFragment() {
class Model @AssistedInject constructor(
@ApplicationContext val context: Context,
application: Application,
val db: AppDatabase,
@Assisted var account: Account,
@Assisted val collectionId: Long
): ViewModel() {
): AndroidViewModel(application) {
@AssistedFactory
interface Factory {
@ -114,7 +113,7 @@ class DeleteCollectionFragment: DialogFragment() {
viewModelScope.launch(Dispatchers.IO + NonCancellable) {
val collectionInfo = collectionInfo ?: return@launch
HttpClient.Builder(context, AccountSettings(context, account))
HttpClient.Builder(getApplication(), AccountSettings(getApplication(), account))
.setForeground(true)
.build().use { httpClient ->
try {

View file

@ -19,6 +19,7 @@ import androidx.appcompat.app.AppCompatActivity
import androidx.core.app.TaskStackBuilder
import androidx.fragment.app.DialogFragment
import androidx.fragment.app.viewModels
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.MediatorLiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
@ -425,10 +426,10 @@ class SettingsActivity: AppCompatActivity() {
class Model @AssistedInject constructor(
val application: Application,
application: Application,
val settings: SettingsManager,
@Assisted val account: Account
): ViewModel(), SettingsManager.OnChangeListener {
): AndroidViewModel(application), SettingsManager.OnChangeListener {
@AssistedFactory
interface Factory {
@ -487,7 +488,9 @@ class SettingsActivity: AppCompatActivity() {
fun reload() {
val accountSettings = accountSettings ?: return
syncIntervalContacts.postValue(accountSettings.getSyncInterval(application.getString(R.string.address_books_authority)))
syncIntervalContacts.postValue(
accountSettings.getSyncInterval(getApplication<Application>().getString(R.string.address_books_authority))
)
syncIntervalCalendars.postValue(accountSettings.getSyncInterval(CalendarContract.AUTHORITY))
syncIntervalTasks.postValue(tasksProvider?.let { accountSettings.getSyncInterval(it.authority) })
@ -570,7 +573,10 @@ class SettingsActivity: AppCompatActivity() {
accountSettings?.setGroupMethod(groupMethod)
reload()
resync(application.getString(R.string.address_books_authority), fullResync = true)
resync(
authority = getApplication<Application>().getString(R.string.address_books_authority),
fullResync = true
)
}
/**
@ -597,7 +603,7 @@ class SettingsActivity: AppCompatActivity() {
*/
private fun resync(authority: String, fullResync: Boolean) {
val resync = if (fullResync) SyncWorker.FULL_RESYNC else SyncWorker.RESYNC
SyncWorker.enqueue(application, account, authority, resync)
SyncWorker.enqueue(getApplication(), account, authority, resync)
}
}

View file

@ -5,6 +5,7 @@
package at.bitfire.davdroid.ui.account
import android.Manifest
import android.app.Application
import android.content.ContentProviderClient
import android.content.Context
import android.content.Intent
@ -33,7 +34,6 @@ import dagger.assisted.Assisted
import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
import dagger.hilt.android.AndroidEntryPoint
import dagger.hilt.android.qualifiers.ApplicationContext
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import okhttp3.HttpUrl
@ -180,16 +180,18 @@ class WebcalFragment: CollectionsFragment() {
class WebcalModel @AssistedInject constructor(
@ApplicationContext context: Context,
application: Application,
val db: AppDatabase,
@Assisted val serviceId: Long
): ViewModel() {
): AndroidViewModel(application) {
@AssistedFactory
interface Factory {
fun create(serviceId: Long): WebcalModel
}
val context: Context get() = getApplication()
private val resolver = context.contentResolver
private var calendarPermission = false

View file

@ -6,6 +6,7 @@ package at.bitfire.davdroid.ui.setup
import android.accounts.Account
import android.accounts.AccountManager
import android.app.Application
import android.content.ContentResolver
import android.content.Context
import android.content.Intent
@ -19,10 +20,10 @@ import android.widget.ArrayAdapter
import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels
import androidx.fragment.app.viewModels
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import at.bitfire.davdroid.InvalidAccountException
import at.bitfire.davdroid.R
@ -44,7 +45,6 @@ import at.bitfire.vcard4android.GroupMethod
import com.google.android.material.snackbar.Snackbar
import dagger.hilt.android.AndroidEntryPoint
import dagger.hilt.android.lifecycle.HiltViewModel
import dagger.hilt.android.qualifiers.ApplicationContext
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.NonCancellable
import kotlinx.coroutines.launch
@ -156,15 +156,17 @@ class AccountDetailsFragment : Fragment() {
@HiltViewModel
class Model @Inject constructor(
@ApplicationContext val context: Context,
application: Application,
val db: AppDatabase,
val settingsManager: SettingsManager
) : ViewModel() {
) : AndroidViewModel(application) {
val name = MutableLiveData<String>()
val nameError = MutableLiveData<String>()
val showApostropheWarning = MutableLiveData<Boolean>(false)
val context: Context get() = getApplication()
fun validateAccountName(s: Editable) {
showApostropheWarning.value = s.toString().contains('\'')
nameError.value = null

View file

@ -4,6 +4,7 @@
package at.bitfire.davdroid.ui.webdav
import android.app.Application
import android.content.Context
import android.os.Bundle
import android.view.Menu
@ -14,8 +15,8 @@ import androidx.activity.viewModels
import androidx.annotation.WorkerThread
import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.MenuProvider
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.lifecycleScope
import at.bitfire.dav4jvm.DavResource
import at.bitfire.dav4jvm.UrlUtils
@ -33,7 +34,6 @@ import at.bitfire.davdroid.webdav.DavDocumentsProvider
import com.google.android.material.snackbar.Snackbar
import dagger.hilt.android.AndroidEntryPoint
import dagger.hilt.android.lifecycle.HiltViewModel
import dagger.hilt.android.qualifiers.ApplicationContext
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import okhttp3.HttpUrl
@ -156,9 +156,9 @@ class AddWebdavMountActivity: AppCompatActivity() {
@HiltViewModel
class Model @Inject constructor(
@ApplicationContext val context: Context,
application: Application,
val db: AppDatabase
) : ViewModel() {
) : AndroidViewModel(application) {
val displayName = MutableLiveData<String>()
val displayNameError = MutableLiveData<String>()
@ -169,6 +169,8 @@ class AddWebdavMountActivity: AppCompatActivity() {
val error = MutableLiveData<String>()
val context: Context get() = getApplication()
@WorkerThread
fun addMount(mount: WebDavMount, credentials: Credentials?): Boolean {

View file

@ -5,6 +5,7 @@
package at.bitfire.davdroid.ui.webdav
import android.app.AlertDialog
import android.app.Application
import android.content.Context
import android.content.Intent
import android.os.Bundle
@ -195,9 +196,11 @@ class WebdavMountsActivity: AppCompatActivity() {
@HiltViewModel
class Model @Inject constructor(
@ApplicationContext val context: Context,
application: Application,
val db: AppDatabase
): ViewModel() {
): AndroidViewModel(application) {
val context: Context get() = getApplication()
val authority = context.getString(R.string.webdav_authority)