mirror of
https://github.com/Aviortheking/Neo-Store.git
synced 2025-04-23 19:32:16 +00:00
Fix some memory leaks and cleanup Repository feature
This commit is contained in:
parent
c599cbc75f
commit
615751fbb1
@ -5,6 +5,7 @@ import androidx.room.Dao
|
|||||||
import androidx.room.Insert
|
import androidx.room.Insert
|
||||||
import androidx.room.Query
|
import androidx.room.Query
|
||||||
import com.looker.droidify.database.entity.Repository
|
import com.looker.droidify.database.entity.Repository
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
|
||||||
@Dao
|
@Dao
|
||||||
interface RepositoryDao : BaseDao<Repository> {
|
interface RepositoryDao : BaseDao<Repository> {
|
||||||
@ -27,6 +28,9 @@ interface RepositoryDao : BaseDao<Repository> {
|
|||||||
@Query("SELECT * FROM repository WHERE _id = :id")
|
@Query("SELECT * FROM repository WHERE _id = :id")
|
||||||
fun getLive(id: Long): LiveData<Repository?>
|
fun getLive(id: Long): LiveData<Repository?>
|
||||||
|
|
||||||
|
@Query("SELECT * FROM repository ORDER BY _id ASC")
|
||||||
|
fun getAllRepositories(): Flow<List<Repository>>
|
||||||
|
|
||||||
@get:Query("SELECT * FROM repository ORDER BY _id ASC")
|
@get:Query("SELECT * FROM repository ORDER BY _id ASC")
|
||||||
val all: List<Repository>
|
val all: List<Repository>
|
||||||
|
|
||||||
@ -38,7 +42,7 @@ interface RepositoryDao : BaseDao<Repository> {
|
|||||||
|
|
||||||
// TODO clean up products and other tables afterwards
|
// TODO clean up products and other tables afterwards
|
||||||
@Query("DELETE FROM repository WHERE _id = :id")
|
@Query("DELETE FROM repository WHERE _id = :id")
|
||||||
fun deleteById(id: Long): Int
|
fun deleteById(id: Long)
|
||||||
|
|
||||||
@Query("SELECT MAX(_id) FROM repository")
|
@Query("SELECT MAX(_id) FROM repository")
|
||||||
fun latestAddedId(): Long
|
fun latestAddedId(): Long
|
||||||
|
@ -43,6 +43,7 @@ import kotlinx.coroutines.flow.asSharedFlow
|
|||||||
import kotlinx.coroutines.flow.launchIn
|
import kotlinx.coroutines.flow.launchIn
|
||||||
import kotlinx.coroutines.flow.onEach
|
import kotlinx.coroutines.flow.onEach
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
import java.lang.ref.WeakReference
|
import java.lang.ref.WeakReference
|
||||||
import kotlin.math.roundToInt
|
import kotlin.math.roundToInt
|
||||||
|
|
||||||
@ -117,7 +118,7 @@ class SyncService : ConnectionService<SyncService.Binder>() {
|
|||||||
fun installApps(products: List<ProductItem>) = batchUpdate(products, true)
|
fun installApps(products: List<ProductItem>) = batchUpdate(products, true)
|
||||||
|
|
||||||
fun sync(request: SyncRequest) {
|
fun sync(request: SyncRequest) {
|
||||||
GlobalScope.launch {
|
scope.launch {
|
||||||
val ids = db.repositoryDao.all.filter { it.enabled }.map { it.id }.toList()
|
val ids = db.repositoryDao.all.filter { it.enabled }.map { it.id }.toList()
|
||||||
sync(ids, request)
|
sync(ids, request)
|
||||||
}
|
}
|
||||||
@ -143,29 +144,30 @@ class SyncService : ConnectionService<SyncService.Binder>() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setEnabled(repository: Repository, enabled: Boolean): Boolean {
|
suspend fun setEnabled(repository: Repository, enabled: Boolean): Boolean =
|
||||||
db.repositoryDao.put(repository.enable(enabled))
|
withContext(Dispatchers.IO) {
|
||||||
if (enabled) {
|
db.repositoryDao.put(repository.enable(enabled))
|
||||||
if (repository.id != currentTask?.task?.repositoryId && !tasks.any { it.repositoryId == repository.id }) {
|
if (enabled) {
|
||||||
synchronized(tasks) { tasks += Task(repository.id, true) }
|
if (repository.id != currentTask?.task?.repositoryId && !tasks.any { it.repositoryId == repository.id }) {
|
||||||
handleNextTask(false)
|
synchronized(tasks) { tasks += Task(repository.id, true) }
|
||||||
|
handleNextTask(false)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
cancelTasks { it.repositoryId == repository.id }
|
||||||
|
synchronized(tasks) { db.cleanUp(setOf(Pair(repository.id, false))) }
|
||||||
|
val cancelledTask = cancelCurrentTask { it.task?.repositoryId == repository.id }
|
||||||
|
handleNextTask(cancelledTask?.hasUpdates == true)
|
||||||
}
|
}
|
||||||
} else {
|
true
|
||||||
cancelTasks { it.repositoryId == repository.id }
|
|
||||||
synchronized(tasks) { db.cleanUp(setOf(Pair(repository.id, false))) }
|
|
||||||
val cancelledTask = cancelCurrentTask { it.task?.repositoryId == repository.id }
|
|
||||||
handleNextTask(cancelledTask?.hasUpdates == true)
|
|
||||||
}
|
}
|
||||||
return true
|
|
||||||
|
suspend fun isCurrentlySyncing(repositoryId: Long): Boolean = withContext(Dispatchers.IO) {
|
||||||
|
currentTask?.task?.repositoryId == repositoryId
|
||||||
}
|
}
|
||||||
|
|
||||||
fun isCurrentlySyncing(repositoryId: Long): Boolean {
|
suspend fun deleteRepository(repositoryId: Long): Boolean = withContext(Dispatchers.IO) {
|
||||||
return currentTask?.task?.repositoryId == repositoryId
|
|
||||||
}
|
|
||||||
|
|
||||||
fun deleteRepository(repositoryId: Long): Boolean {
|
|
||||||
val repository = db.repositoryDao.get(repositoryId)
|
val repository = db.repositoryDao.get(repositoryId)
|
||||||
return repository != null && run {
|
repository != null && run {
|
||||||
setEnabled(repository, false)
|
setEnabled(repository, false)
|
||||||
db.repositoryDao.deleteById(repository.id)
|
db.repositoryDao.deleteById(repository.id)
|
||||||
true
|
true
|
||||||
@ -325,7 +327,7 @@ class SyncService : ConnectionService<SyncService.Binder>() {
|
|||||||
|
|
||||||
private fun handleNextTask(hasUpdates: Boolean) {
|
private fun handleNextTask(hasUpdates: Boolean) {
|
||||||
if (currentTask == null) {
|
if (currentTask == null) {
|
||||||
GlobalScope.launch {
|
scope.launch {
|
||||||
if (tasks.isNotEmpty()) {
|
if (tasks.isNotEmpty()) {
|
||||||
val task = tasks.removeAt(0)
|
val task = tasks.removeAt(0)
|
||||||
val repository = db.repositoryDao.get(task.repositoryId)
|
val repository = db.repositoryDao.get(task.repositoryId)
|
||||||
@ -425,7 +427,7 @@ class SyncService : ConnectionService<SyncService.Binder>() {
|
|||||||
* @see SyncService.displayUpdatesNotification
|
* @see SyncService.displayUpdatesNotification
|
||||||
*/
|
*/
|
||||||
private fun batchUpdate(productItems: List<ProductItem>, install: Boolean = false) {
|
private fun batchUpdate(productItems: List<ProductItem>, install: Boolean = false) {
|
||||||
if (Preferences[Preferences.Key.InstallAfterSync]) GlobalScope.launch {
|
if (Preferences[Preferences.Key.InstallAfterSync]) scope.launch {
|
||||||
// run startUpdate on every item
|
// run startUpdate on every item
|
||||||
productItems.map { productItem ->
|
productItems.map { productItem ->
|
||||||
Triple(
|
Triple(
|
||||||
|
@ -29,7 +29,7 @@ fun RepositoryPage(viewModel: RepositoriesViewModelX) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
) {
|
) {
|
||||||
val sortedRepoList = remember { repos.sortedBy { !it.enabled } }
|
val sortedRepoList = remember(repos) { repos.sortedBy { !it.enabled } }
|
||||||
RepositoriesRecycler(
|
RepositoriesRecycler(
|
||||||
repositoriesList = sortedRepoList,
|
repositoriesList = sortedRepoList,
|
||||||
onClick = { viewModel.toggleRepository(it, it.enabled) },
|
onClick = { viewModel.toggleRepository(it, it.enabled) },
|
||||||
|
@ -15,6 +15,7 @@ import androidx.appcompat.app.AlertDialog
|
|||||||
import androidx.core.widget.doAfterTextChanged
|
import androidx.core.widget.doAfterTextChanged
|
||||||
import androidx.fragment.app.DialogFragment
|
import androidx.fragment.app.DialogFragment
|
||||||
import androidx.fragment.app.viewModels
|
import androidx.fragment.app.viewModels
|
||||||
|
import androidx.lifecycle.lifecycleScope
|
||||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||||
import com.looker.droidify.EXTRA_REPOSITORY_ID
|
import com.looker.droidify.EXTRA_REPOSITORY_ID
|
||||||
import com.looker.droidify.R
|
import com.looker.droidify.R
|
||||||
@ -33,9 +34,8 @@ import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
|
|||||||
import io.reactivex.rxjava3.core.Single
|
import io.reactivex.rxjava3.core.Single
|
||||||
import io.reactivex.rxjava3.disposables.Disposable
|
import io.reactivex.rxjava3.disposables.Disposable
|
||||||
import io.reactivex.rxjava3.schedulers.Schedulers
|
import io.reactivex.rxjava3.schedulers.Schedulers
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.GlobalScope
|
|
||||||
import kotlinx.coroutines.MainScope
|
import kotlinx.coroutines.MainScope
|
||||||
|
import kotlinx.coroutines.flow.collectLatest
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import okhttp3.HttpUrl.Companion.toHttpUrl
|
import okhttp3.HttpUrl.Companion.toHttpUrl
|
||||||
import okhttp3.Request
|
import okhttp3.Request
|
||||||
@ -138,12 +138,14 @@ class EditRepositorySheetX() : FullscreenBottomSheetDialogFragment(), RepoManage
|
|||||||
.show(childFragmentManager)
|
.show(childFragmentManager)
|
||||||
}
|
}
|
||||||
|
|
||||||
GlobalScope.launch {
|
lifecycleScope.launchWhenStarted {
|
||||||
val list = viewModel.db.repositoryDao.all
|
val reposFlow = viewModel.db.repositoryDao.getAllRepositories()
|
||||||
takenAddresses = list.asSequence().filter { it.id != repositoryId }
|
reposFlow.collectLatest { list ->
|
||||||
.flatMap { (it.mirrors + it.address).asSequence() }
|
takenAddresses = list.asSequence().filter { it.id != repositoryId }
|
||||||
.map { it.withoutKnownPath }.toSet()
|
.flatMap { (it.mirrors + it.address).asSequence() }
|
||||||
MainScope().launch { invalidateAddress() }
|
.map { it.withoutKnownPath }.toSet()
|
||||||
|
MainScope().launch { invalidateAddress() }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -389,7 +391,7 @@ class EditRepositorySheetX() : FullscreenBottomSheetDialogFragment(), RepoManage
|
|||||||
address: String,
|
address: String,
|
||||||
fingerprint: String,
|
fingerprint: String,
|
||||||
authentication: String,
|
authentication: String,
|
||||||
) = GlobalScope.launch {
|
) = lifecycleScope.launch {
|
||||||
val binder = syncConnection.binder
|
val binder = syncConnection.binder
|
||||||
if (binder != null) {
|
if (binder != null) {
|
||||||
if (binder.isCurrentlySyncing(repositoryId)) {
|
if (binder.isCurrentlySyncing(repositoryId)) {
|
||||||
@ -435,7 +437,7 @@ class EditRepositorySheetX() : FullscreenBottomSheetDialogFragment(), RepoManage
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun onDeleteConfirm() {
|
override fun onDeleteConfirm() {
|
||||||
GlobalScope.launch(Dispatchers.IO) {
|
lifecycleScope.launch {
|
||||||
if (syncConnection.binder?.deleteRepository(repositoryId) == true)
|
if (syncConnection.binder?.deleteRepository(repositoryId) == true)
|
||||||
dismissAllowingStateLoss()
|
dismissAllowingStateLoss()
|
||||||
}
|
}
|
||||||
|
@ -32,7 +32,7 @@ class PrefsRepositoriesFragment : BaseNavFragment() {
|
|||||||
savedInstanceState: Bundle?,
|
savedInstanceState: Bundle?,
|
||||||
): View {
|
): View {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
lifecycleScope.launchWhenCreated {
|
lifecycleScope.launchWhenStarted {
|
||||||
viewModel.showSheet.collectLatest {
|
viewModel.showSheet.collectLatest {
|
||||||
it?.let {
|
it?.let {
|
||||||
RepositorySheetX(it).showNow(childFragmentManager, "Repository $it")
|
RepositorySheetX(it).showNow(childFragmentManager, "Repository $it")
|
||||||
|
@ -9,6 +9,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.viewModels
|
import androidx.fragment.app.viewModels
|
||||||
|
import androidx.lifecycle.lifecycleScope
|
||||||
import com.looker.droidify.EXTRA_REPOSITORY_ID
|
import com.looker.droidify.EXTRA_REPOSITORY_ID
|
||||||
import com.looker.droidify.R
|
import com.looker.droidify.R
|
||||||
import com.looker.droidify.RepoManager
|
import com.looker.droidify.RepoManager
|
||||||
@ -19,8 +20,6 @@ import com.looker.droidify.service.SyncService
|
|||||||
import com.looker.droidify.ui.activities.PrefsActivityX
|
import com.looker.droidify.ui.activities.PrefsActivityX
|
||||||
import com.looker.droidify.ui.viewmodels.RepositoryViewModelX
|
import com.looker.droidify.ui.viewmodels.RepositoryViewModelX
|
||||||
import com.looker.droidify.utility.extension.resources.getColorFromAttr
|
import com.looker.droidify.utility.extension.resources.getColorFromAttr
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.GlobalScope
|
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
@ -140,7 +139,7 @@ class RepositorySheetX() : FullscreenBottomSheetDialogFragment(), RepoManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun onDeleteConfirm() {
|
override fun onDeleteConfirm() {
|
||||||
GlobalScope.launch(Dispatchers.IO) {
|
lifecycleScope.launch {
|
||||||
if (syncConnection.binder?.deleteRepository(repositoryId) == true)
|
if (syncConnection.binder?.deleteRepository(repositoryId) == true)
|
||||||
dismissAllowingStateLoss()
|
dismissAllowingStateLoss()
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,7 @@ import com.looker.droidify.service.SyncService
|
|||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import kotlinx.coroutines.flow.asStateFlow
|
import kotlinx.coroutines.flow.asStateFlow
|
||||||
|
import kotlinx.coroutines.flow.collectLatest
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
|
|
||||||
@ -30,7 +31,9 @@ class RepositoriesViewModelX(val repositoryDao: RepositoryDao) : ViewModel() {
|
|||||||
|
|
||||||
init {
|
init {
|
||||||
viewModelScope.launch(Dispatchers.IO) {
|
viewModelScope.launch(Dispatchers.IO) {
|
||||||
_repositories.emit(repositoryDao.all)
|
repositoryDao.getAllRepositories().collectLatest {
|
||||||
|
_repositories.emit(it)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
toLaunch.value = null
|
toLaunch.value = null
|
||||||
}
|
}
|
||||||
@ -40,13 +43,11 @@ class RepositoriesViewModelX(val repositoryDao: RepositoryDao) : ViewModel() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun showRepositorySheet(repositoryId: Long) {
|
fun showRepositorySheet(repositoryId: Long) {
|
||||||
viewModelScope.launch {
|
viewModelScope.launch { _showSheet.emit(repositoryId) }
|
||||||
_showSheet.emit(repositoryId)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun toggleRepository(repository: Repository, isEnabled: Boolean) {
|
fun toggleRepository(repository: Repository, isEnabled: Boolean) {
|
||||||
viewModelScope.launch(Dispatchers.IO) {
|
viewModelScope.launch {
|
||||||
syncConnection.binder?.setEnabled(repository, isEnabled)
|
syncConnection.binder?.setEnabled(repository, isEnabled)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user