瀏覽代碼

Reduce stutter when entering Browse screen (#6435)

* More coil

* ExtensionController: Drop first text change event

* Browse-Source: Remove unnecessary load

* ExtensionPresenter: Increase debounce timeout

To avoid heavy list reload during first enter animation
Ivan Iskandar 3 年之前
父節點
當前提交
78a261f5d3

+ 2 - 0
app/src/main/java/eu/kanade/tachiyomi/extension/model/Extension.kt

@@ -1,5 +1,6 @@
 package eu.kanade.tachiyomi.extension.model
 
+import android.graphics.drawable.Drawable
 import eu.kanade.tachiyomi.source.Source
 
 sealed class Extension {
@@ -20,6 +21,7 @@ sealed class Extension {
         override val isNsfw: Boolean,
         val pkgFactory: String?,
         val sources: List<Source>,
+        val icon: Drawable?,
         val hasUpdate: Boolean = false,
         val isObsolete: Boolean = false,
         val isUnofficial: Boolean = false

+ 3 - 1
app/src/main/java/eu/kanade/tachiyomi/extension/util/ExtensionLoader.kt

@@ -13,6 +13,7 @@ import eu.kanade.tachiyomi.source.CatalogueSource
 import eu.kanade.tachiyomi.source.Source
 import eu.kanade.tachiyomi.source.SourceFactory
 import eu.kanade.tachiyomi.util.lang.Hash
+import eu.kanade.tachiyomi.util.system.getApplicationIcon
 import eu.kanade.tachiyomi.util.system.logcat
 import kotlinx.coroutines.async
 import kotlinx.coroutines.runBlocking
@@ -181,7 +182,8 @@ internal object ExtensionLoader {
             isNsfw,
             sources = sources,
             pkgFactory = appInfo.metaData.getString(METADATA_SOURCE_FACTORY),
-            isUnofficial = signatureHash != officialSignature
+            isUnofficial = signatureHash != officialSignature,
+            icon = context.getApplicationIcon(pkgName)
         )
         return LoadResult.Success(extension)
     }

+ 2 - 0
app/src/main/java/eu/kanade/tachiyomi/ui/browse/extension/ExtensionController.kt

@@ -20,6 +20,7 @@ import eu.kanade.tachiyomi.ui.base.controller.NucleusController
 import eu.kanade.tachiyomi.ui.base.controller.withFadeTransaction
 import eu.kanade.tachiyomi.ui.browse.BrowseController
 import eu.kanade.tachiyomi.ui.browse.extension.details.ExtensionDetailsController
+import kotlinx.coroutines.flow.drop
 import kotlinx.coroutines.flow.filter
 import kotlinx.coroutines.flow.launchIn
 import kotlinx.coroutines.flow.onEach
@@ -143,6 +144,7 @@ open class ExtensionController :
         }
 
         searchView.queryTextChanges()
+            .drop(1) // Drop first event after subscribed
             .filter { router.backstack.lastOrNull()?.controller == this }
             .onEach {
                 query = it.toString()

+ 2 - 2
app/src/main/java/eu/kanade/tachiyomi/ui/browse/extension/ExtensionHolder.kt

@@ -42,8 +42,8 @@ class ExtensionHolder(view: View, val adapter: ExtensionAdapter) :
         binding.icon.clear()
         if (extension is Extension.Available) {
             binding.icon.load(extension.iconUrl)
-        } else {
-            extension.getApplicationIcon(itemView.context)?.let { binding.icon.setImageDrawable(it) }
+        } else if (extension is Extension.Installed) {
+            binding.icon.load(extension.icon)
         }
         bindButtons(item)
     }

+ 1 - 1
app/src/main/java/eu/kanade/tachiyomi/ui/browse/extension/ExtensionPresenter.kt

@@ -47,7 +47,7 @@ open class ExtensionPresenter(
             .startWith(emptyList<Extension.Available>())
 
         return Observable.combineLatest(installedObservable, untrustedObservable, availableObservable) { installed, untrusted, available -> Triple(installed, untrusted, available) }
-            .debounce(100, TimeUnit.MILLISECONDS)
+            .debounce(500, TimeUnit.MILLISECONDS)
             .map(::toItems)
             .observeOn(AndroidSchedulers.mainThread())
             .subscribeLatestCache({ view, _ -> view.setExtensions(extensions) })

+ 2 - 1
app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/sources/SourceHolder.kt

@@ -2,6 +2,7 @@ package eu.kanade.tachiyomi.ui.browse.migration.sources
 
 import android.view.View
 import androidx.core.view.isVisible
+import coil.load
 import eu.davidea.viewholders.FlexibleViewHolder
 import eu.kanade.tachiyomi.databinding.SourceMainControllerItemBinding
 import eu.kanade.tachiyomi.source.icon
@@ -20,7 +21,7 @@ class SourceHolder(view: View, val adapter: SourceAdapter) :
         binding.subtitle.text = LocaleHelper.getDisplayName(source.lang)
 
         itemView.post {
-            binding.image.setImageDrawable(source.icon())
+            binding.image.load(source.icon())
         }
     }
 }

+ 1 - 0
app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/SourceController.kt

@@ -92,6 +92,7 @@ class SourceController :
 
         // Update list on extension changes (e.g. new installation)
         (parentController as BrowseController).extensionListUpdateRelay
+            .skip(1) // Skip first update when ExtensionController created
             .subscribeUntilDestroy {
                 presenter.updateSources()
             }

+ 6 - 7
app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/SourceHolder.kt

@@ -2,6 +2,7 @@ package eu.kanade.tachiyomi.ui.browse.source
 
 import android.view.View
 import androidx.core.view.isVisible
+import coil.load
 import eu.davidea.viewholders.FlexibleViewHolder
 import eu.kanade.tachiyomi.R
 import eu.kanade.tachiyomi.databinding.SourceMainControllerItemBinding
@@ -10,7 +11,7 @@ import eu.kanade.tachiyomi.source.icon
 import eu.kanade.tachiyomi.util.system.LocaleHelper
 import eu.kanade.tachiyomi.util.view.setVectorCompat
 
-class SourceHolder(private val view: View, val adapter: SourceAdapter) :
+class SourceHolder(view: View, val adapter: SourceAdapter) :
     FlexibleViewHolder(view, adapter) {
 
     private val binding = SourceMainControllerItemBinding.bind(view)
@@ -33,12 +34,10 @@ class SourceHolder(private val view: View, val adapter: SourceAdapter) :
         binding.subtitle.text = LocaleHelper.getDisplayName(source.lang)
 
         // Set source icon
-        itemView.post {
-            val icon = source.icon()
-            when {
-                icon != null -> binding.image.setImageDrawable(icon)
-                item.source.id == LocalSource.ID -> binding.image.setImageResource(R.mipmap.ic_local_source)
-            }
+        val icon = source.icon()
+        when {
+            icon != null -> binding.image.load(icon)
+            item.source.id == LocalSource.ID -> binding.image.load(R.mipmap.ic_local_source)
         }
 
         binding.sourceLatest.isVisible = source.supportsLatest

+ 0 - 9
app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/SourcePresenter.kt

@@ -1,6 +1,5 @@
 package eu.kanade.tachiyomi.ui.browse.source
 
-import android.os.Bundle
 import eu.kanade.tachiyomi.data.preference.PreferencesHelper
 import eu.kanade.tachiyomi.source.CatalogueSource
 import eu.kanade.tachiyomi.source.LocalSource
@@ -37,14 +36,6 @@ class SourcePresenter(
      */
     private var sourceSubscription: Subscription? = null
 
-    override fun onCreate(savedState: Bundle?) {
-        super.onCreate(savedState)
-
-        // Load enabled and last used sources
-        loadSources()
-        loadLastUsedSource()
-    }
-
     /**
      * Unsubscribe and create a new subscription to fetch enabled sources.
      */

+ 9 - 0
app/src/main/java/eu/kanade/tachiyomi/util/system/ContextExtensions.kt

@@ -14,6 +14,7 @@ import android.content.pm.PackageManager
 import android.content.res.Configuration
 import android.content.res.Resources
 import android.graphics.Color
+import android.graphics.drawable.Drawable
 import android.net.ConnectivityManager
 import android.net.NetworkCapabilities
 import android.net.Uri
@@ -418,3 +419,11 @@ fun Context.isPackageInstalled(packageName: String): Boolean {
         false
     }
 }
+
+fun Context.getApplicationIcon(pkgName: String): Drawable? {
+    return try {
+        packageManager.getApplicationIcon(pkgName)
+    } catch (e: PackageManager.NameNotFoundException) {
+        null
+    }
+}