Remove: Allowing queries on MainThread

This commit is contained in:
machiav3lli 2022-01-13 00:53:40 +01:00
parent 251b6195d6
commit d427968ccb
8 changed files with 111 additions and 102 deletions

View File

@ -86,7 +86,9 @@ class MainApplication : Application(), ImageLoaderFactory {
val installedItems = val installedItems =
packageManager.getInstalledPackages(Android.PackageManager.signaturesFlag) packageManager.getInstalledPackages(Android.PackageManager.signaturesFlag)
.map { it.toInstalledItem() } .map { it.toInstalledItem() }
db.installedDao.put(*installedItems.toTypedArray()) CoroutineScope(Dispatchers.Default).launch {
db.installedDao.put(*installedItems.toTypedArray())
}
} }
private fun listenPreferences() { private fun listenPreferences() {

View File

@ -12,7 +12,6 @@ import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.asSharedFlow import kotlinx.coroutines.flow.asSharedFlow
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import java.io.ByteArrayOutputStream import java.io.ByteArrayOutputStream
import java.nio.charset.Charset import java.nio.charset.Charset
@ -27,23 +26,23 @@ object ProductPreferences {
fun init(context: Context) { fun init(context: Context) {
db = DatabaseX.getInstance(context) db = DatabaseX.getInstance(context)
preferences = context.getSharedPreferences("product_preferences", Context.MODE_PRIVATE) preferences = context.getSharedPreferences("product_preferences", Context.MODE_PRIVATE)
db.lockDao.insert(*preferences.all.keys CoroutineScope(Dispatchers.Default).launch {
.mapNotNull { pName -> db.lockDao.insert(*preferences.all.keys
this[pName].databaseVersionCode?.let { .mapNotNull { pName ->
Lock().apply { this@ProductPreferences[pName].databaseVersionCode?.let {
package_name = pName Lock().apply {
version_code = it package_name = pName
version_code = it
}
} }
} }
} .toTypedArray()
.toTypedArray() )
)
CoroutineScope(Dispatchers.Default).launch {
subject.collect { (packageName, versionCode) -> subject.collect { (packageName, versionCode) ->
if (versionCode != null) db.lockDao.insert(Lock().apply { if (versionCode != null) db.lockDao.insert(Lock().apply {
package_name = packageName package_name = packageName
version_code = versionCode version_code = versionCode
} }
) )
else db.lockDao.delete(packageName) else db.lockDao.delete(packageName)
} }

View File

@ -6,6 +6,9 @@ import androidx.room.Room
import androidx.room.RoomDatabase import androidx.room.RoomDatabase
import androidx.room.TypeConverters import androidx.room.TypeConverters
import com.looker.droidify.entity.Repository.Companion.defaultRepositories import com.looker.droidify.entity.Repository.Companion.defaultRepositories
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
@Database( @Database(
entities = [ entities = [
@ -42,11 +45,12 @@ abstract class DatabaseX : RoomDatabase() {
"main_database.db" "main_database.db"
) )
.fallbackToDestructiveMigration() .fallbackToDestructiveMigration()
.allowMainThreadQueries()
.build() .build()
INSTANCE?.let { instance -> INSTANCE?.let { instance ->
if (instance.repositoryDao.count == 0) defaultRepositories.forEach { GlobalScope.launch(Dispatchers.IO) {
instance.repositoryDao.put(it) if (instance.repositoryDao.count == 0) defaultRepositories.forEach {
instance.repositoryDao.put(it)
}
} }
} }
} }

View File

@ -99,9 +99,11 @@ class SyncService : ConnectionService<SyncService.Binder>() {
} }
fun sync(request: SyncRequest) { fun sync(request: SyncRequest) {
val ids = db.repositoryDao.all.mapNotNull { it.trueData } GlobalScope.launch {
.asSequence().filter { it.enabled }.map { it.id }.toList() val ids = db.repositoryDao.all.mapNotNull { it.trueData }
sync(ids, request) .asSequence().filter { it.enabled }.map { it.id }.toList()
sync(ids, request)
}
} }
fun sync(repository: Repository) { fun sync(repository: Repository) {
@ -332,92 +334,94 @@ class SyncService : ConnectionService<SyncService.Binder>() {
private fun handleNextTask(hasUpdates: Boolean) { private fun handleNextTask(hasUpdates: Boolean) {
if (currentTask == null) { if (currentTask == null) {
if (tasks.isNotEmpty()) { GlobalScope.launch {
val task = tasks.removeAt(0) if (tasks.isNotEmpty()) {
val repository = db.repositoryDao.get(task.repositoryId)?.trueData val task = tasks.removeAt(0)
if (repository != null && repository.enabled) { val repository = db.repositoryDao.get(task.repositoryId)?.trueData
val lastStarted = started if (repository != null && repository.enabled) {
val newStarted = val lastStarted = started
if (task.manual || lastStarted == Started.MANUAL) Started.MANUAL else Started.AUTO val newStarted =
started = newStarted if (task.manual || lastStarted == Started.MANUAL) Started.MANUAL else Started.AUTO
if (newStarted == Started.MANUAL && lastStarted != Started.MANUAL) { started = newStarted
startSelf() if (newStarted == Started.MANUAL && lastStarted != Started.MANUAL) {
handleSetStarted() startSelf()
} handleSetStarted()
val initialState = State.Connecting(repository.name) }
publishForegroundState(true, initialState) val initialState = State.Connecting(repository.name)
val unstable = Preferences[Preferences.Key.UpdateUnstable] publishForegroundState(true, initialState)
lateinit var disposable: Disposable val unstable = Preferences[Preferences.Key.UpdateUnstable]
disposable = RepositoryUpdater lateinit var disposable: Disposable
.update(this, repository, unstable) { stage, progress, total -> disposable = RepositoryUpdater
if (!disposable.isDisposed) { .update(this@SyncService, repository, unstable) { stage, progress, total ->
scope.launch { if (!disposable.isDisposed) {
mutableStateSubject.emit( scope.launch {
State.Syncing( mutableStateSubject.emit(
repository.name, State.Syncing(
stage, repository.name,
progress, stage,
total progress,
total
)
) )
) }
} }
} }
.observeOn(AndroidSchedulers.mainThread())
.subscribe { result, throwable ->
currentTask = null
throwable?.printStackTrace()
if (throwable != null && task.manual) {
showNotificationError(repository, throwable as Exception)
}
handleNextTask(result == true || hasUpdates)
}
currentTask = CurrentTask(task, disposable, hasUpdates, initialState)
} else {
handleNextTask(hasUpdates)
}
} else if (started != Started.NO) {
val disposable = RxUtils
.querySingle { it ->
db.productDao
.query(
installed = true,
updates = true,
searchQuery = "",
section = ProductItem.Section.All,
order = ProductItem.Order.NAME,
signal = it
)
.use {
it.asSequence().map { it.getProductItem() }
.toList()
}
} }
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())
.subscribe { result, throwable -> .subscribe { result, throwable ->
currentTask = null
throwable?.printStackTrace() throwable?.printStackTrace()
if (throwable != null && task.manual) { currentTask = null
showNotificationError(repository, throwable as Exception) handleNextTask(false)
if (result.isNotEmpty()) {
if (Preferences[Preferences.Key.InstallAfterSync])
runAutoUpdate(result)
if (hasUpdates && Preferences[Preferences.Key.UpdateNotify] &&
updateNotificationBlockerFragment?.get()?.isAdded == true
)
displayUpdatesNotification(result)
} }
handleNextTask(result == true || hasUpdates)
} }
currentTask = CurrentTask(task, disposable, hasUpdates, initialState) if (hasUpdates) {
} else { currentTask = CurrentTask(null, disposable, true, State.Finishing)
handleNextTask(hasUpdates) } else {
} scope.launch { mutableFinishState.emit(Unit) }
} else if (started != Started.NO) { val needStop = started == Started.MANUAL
val disposable = RxUtils started = Started.NO
.querySingle { it -> if (needStop) {
db.productDao stopForeground(true)
.query( stopSelf()
installed = true,
updates = true,
searchQuery = "",
section = ProductItem.Section.All,
order = ProductItem.Order.NAME,
signal = it
)
.use {
it.asSequence().map { it.getProductItem() }
.toList()
}
}
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe { result, throwable ->
throwable?.printStackTrace()
currentTask = null
handleNextTask(false)
if (result.isNotEmpty()) {
if (Preferences[Preferences.Key.InstallAfterSync])
runAutoUpdate(result)
if (hasUpdates && Preferences[Preferences.Key.UpdateNotify] &&
updateNotificationBlockerFragment?.get()?.isAdded == true
)
displayUpdatesNotification(result)
} }
} }
if (hasUpdates) {
currentTask = CurrentTask(null, disposable, true, State.Finishing)
} else {
scope.launch { mutableFinishState.emit(Unit) }
val needStop = started == Started.MANUAL
started = Started.NO
if (needStop) {
stopForeground(true)
stopSelf()
}
} }
} }
} }

View File

@ -63,7 +63,7 @@ class ExploreFragment : MainNavFragmentX(), CursorOwner.Callback {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
viewModel.fillList(source) //viewModel.fillList(source)
viewModel.db.repositoryDao.allFlowable viewModel.db.repositoryDao.allFlowable
.observeOn(Schedulers.io()) .observeOn(Schedulers.io())
.flatMapSingle { list -> RxUtils.querySingle { list.mapNotNull { it.trueData } } } .flatMapSingle { list -> RxUtils.querySingle { list.mapNotNull { it.trueData } } }

View File

@ -80,7 +80,7 @@ class InstalledFragment : MainNavFragmentX(), CursorOwner.Callback {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
viewModel.fillList(source) //viewModel.fillList(source)
viewModel.db.repositoryDao.allFlowable viewModel.db.repositoryDao.allFlowable
.observeOn(Schedulers.io()) .observeOn(Schedulers.io())
.flatMapSingle { list -> RxUtils.querySingle { list.mapNotNull { it.trueData } } } .flatMapSingle { list -> RxUtils.querySingle { list.mapNotNull { it.trueData } } }

View File

@ -80,7 +80,7 @@ class LatestFragment : MainNavFragmentX(), CursorOwner.Callback {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
viewModel.fillList(source) //viewModel.fillList(source)
viewModel.db.repositoryDao.allFlowable viewModel.db.repositoryDao.allFlowable
.observeOn(Schedulers.io()) .observeOn(Schedulers.io())
.flatMapSingle { list -> RxUtils.querySingle { list.mapNotNull { it.trueData } } } .flatMapSingle { list -> RxUtils.querySingle { list.mapNotNull { it.trueData } } }

View File

@ -18,7 +18,7 @@ abstract class MainNavFragmentX : Fragment(), CursorOwner.Callback {
internal fun setSearchQuery(searchQuery: String) { internal fun setSearchQuery(searchQuery: String) {
viewModel.setSearchQuery(searchQuery) { viewModel.setSearchQuery(searchQuery) {
if (view != null) { if (view != null) {
viewModel.fillList(source) //viewModel.fillList(source)
} }
} }
} }
@ -26,7 +26,7 @@ abstract class MainNavFragmentX : Fragment(), CursorOwner.Callback {
internal fun setSection(section: ProductItem.Section) { internal fun setSection(section: ProductItem.Section) {
viewModel.setSection(section) { viewModel.setSection(section) {
if (view != null) { if (view != null) {
viewModel.fillList(source) //viewModel.fillList(source)
} }
} }
} }
@ -34,7 +34,7 @@ abstract class MainNavFragmentX : Fragment(), CursorOwner.Callback {
internal fun setOrder(order: ProductItem.Order) { internal fun setOrder(order: ProductItem.Order) {
viewModel.setOrder(order) { viewModel.setOrder(order) {
if (view != null) { if (view != null) {
viewModel.fillList(source) //viewModel.fillList(source)
} }
} }
} }