mirror of
https://github.com/Michatec/michas-droid.git
synced 2026-05-30 18:02:43 +02:00
- Refactor code to use idiomatic Kotlin functions like isNullOrEmpty(), associateBy, and appendRange
- Increase `DiffUtil` threshold in `CursorRecyclerAdapter` to 500 and optimize equality checks - Simplify locale configuration by removing legacy Android SDK version checks - Remove unnecessary `@SuppressLint` annotations and `@Volatile` modifiers - Improve performance of collection operations in `ProductFragment` and `Preferences` using `associateBy` and `firstOrNull` - Suppress deprecation warnings for `getOpacity` in `DrawableWrapper` and `TabsFragment` - Clean up service binding logic in `Connection.kt` with better type casting
This commit is contained in:
@@ -16,10 +16,12 @@ object Preferences {
|
||||
|
||||
private val subject = PublishSubject.create<Key<*>>()
|
||||
|
||||
private val keys = sequenceOf(Key.AutoSync, Key.IncompatibleVersions, Key.ProxyHost, Key.ProxyPort, Key.ProxyType,
|
||||
Key.SortOrder, Key.Theme, Key.UpdateNotify, Key.UpdateUnstable).map { Pair(it.name, it) }.toMap()
|
||||
private val keys = sequenceOf(
|
||||
Key.AutoSync, Key.IncompatibleVersions, Key.ProxyHost, Key.ProxyPort, Key.ProxyType,
|
||||
Key.SortOrder, Key.Theme, Key.UpdateNotify, Key.UpdateUnstable
|
||||
).associateBy { it.name }
|
||||
|
||||
private val listener = SharedPreferences.OnSharedPreferenceChangeListener { _, keyString ->
|
||||
private val listener = SharedPreferences.OnSharedPreferenceChangeListener { _, keyString ->
|
||||
keys[keyString]?.let(subject::onNext)
|
||||
}
|
||||
|
||||
|
||||
@@ -74,5 +74,6 @@ open class DrawableWrapper(val drawable: Drawable): Drawable() {
|
||||
DrawableCompat.setHotspotBounds(drawable, left, top, right, bottom)
|
||||
}
|
||||
|
||||
@Suppress("DEPRECATION", "OVERRIDE_DEPRECATION")
|
||||
override fun getOpacity(): Int = drawable.opacity
|
||||
}
|
||||
|
||||
@@ -260,6 +260,6 @@ class IndexHandler(private val repositoryId: Long, private val callback: Callbac
|
||||
|
||||
override fun characters(ch: CharArray, start: Int, length: Int) {
|
||||
super.characters(ch, start, length)
|
||||
contentBuilder.append(ch, start, length)
|
||||
contentBuilder.appendRange(ch, start, start + length)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -362,10 +362,10 @@ class ProductAdapter(private val callbacks: Callbacks, private val columns: Int)
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressLint("ClickableViewAccessibility")
|
||||
private open class OverlappingViewHolder(itemView: View): RecyclerView.ViewHolder(itemView) {
|
||||
init {
|
||||
// Block touch events if touched above negative margin
|
||||
@SuppressLint("ClickableViewAccessibility")
|
||||
itemView.setOnTouchListener { v, event ->
|
||||
val top = (v.layoutParams as ViewGroup.MarginLayoutParams).topMargin
|
||||
event.action == MotionEvent.ACTION_DOWN && top < 0 && event.y < -top
|
||||
@@ -373,6 +373,7 @@ class ProductAdapter(private val callbacks: Callbacks, private val columns: Int)
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressLint("SetTextI18n")
|
||||
private class LinkViewHolder(itemView: View): OverlappingViewHolder(itemView) {
|
||||
companion object {
|
||||
private val measurement = Measurement<Int>()
|
||||
@@ -384,7 +385,6 @@ class ProductAdapter(private val callbacks: Callbacks, private val columns: Int)
|
||||
|
||||
init {
|
||||
val margin = measurement.invalidate(itemView.resources) {
|
||||
@SuppressLint("SetTextI18n")
|
||||
text.text = "measure"
|
||||
link.visibility = View.GONE
|
||||
measurement.measure(itemView)
|
||||
@@ -397,6 +397,7 @@ class ProductAdapter(private val callbacks: Callbacks, private val columns: Int)
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressLint("SetTextI18n")
|
||||
private class PermissionsViewHolder(itemView: View): OverlappingViewHolder(itemView) {
|
||||
companion object {
|
||||
private val measurement = Measurement<Int>()
|
||||
@@ -407,7 +408,6 @@ class ProductAdapter(private val callbacks: Callbacks, private val columns: Int)
|
||||
|
||||
init {
|
||||
val margin = measurement.invalidate(itemView.resources) {
|
||||
@SuppressLint("SetTextI18n")
|
||||
text.text = "measure"
|
||||
measurement.measure(itemView)
|
||||
((itemView.measuredHeight - icon.measuredHeight) / 2f).roundToInt()
|
||||
|
||||
@@ -148,8 +148,8 @@ class ProductFragment(): ScreenFragment(), ProductAdapter.Callbacks {
|
||||
.flatMapSingle { products -> RxUtils
|
||||
.querySingle { signal -> Database.RepositoryAdapter.getAll(signal) }
|
||||
.map { result ->
|
||||
result.asSequence().map { Pair(it.id, it) }.toMap()
|
||||
.let { map -> products.mapNotNull { product -> map[product.repositoryId]?.let { Pair(product, it) } } } } }
|
||||
result.associateBy { it.id }
|
||||
.let { map -> products.mapNotNull { product -> map[product.repositoryId]?.let { Pair(product, it) } } } } }
|
||||
.flatMapSingle { products -> RxUtils
|
||||
.querySingle { signal -> Nullable(Database.InstalledAdapter.get(packageName, signal)) }
|
||||
.map { result -> Pair(products, result) } }
|
||||
@@ -396,9 +396,9 @@ class ProductFragment(): ScreenFragment(), ProductAdapter.Callbacks {
|
||||
|
||||
override fun onScreenshotClick(screenshot: Product.Screenshot) {
|
||||
val pair = products.asSequence()
|
||||
.map { it -> Pair(it.second, it.first.screenshots.find { it === screenshot }?.identifier) }
|
||||
.filter { it.second != null }.firstOrNull()
|
||||
if (pair != null) {
|
||||
.map { it -> Pair(it.second, it.first.screenshots.find { it === screenshot }?.identifier) }
|
||||
.firstOrNull { it.second != null }
|
||||
if (pair != null) {
|
||||
val (repository, identifier) = pair
|
||||
if (identifier != null) {
|
||||
ScreenshotsFragment(packageName, repository.id, identifier).show(childFragmentManager)
|
||||
@@ -420,8 +420,9 @@ class ProductFragment(): ScreenFragment(), ProductAdapter.Callbacks {
|
||||
MessageDialog(MessageDialog.Message.ReleaseSignatureMismatch).show(childFragmentManager)
|
||||
}
|
||||
else -> {
|
||||
val productRepository = products.asSequence().filter { it -> it.first.releases.any { it === release } }.firstOrNull()
|
||||
if (productRepository != null) {
|
||||
val productRepository =
|
||||
products.firstOrNull { it -> it.first.releases.any { it === release } }
|
||||
if (productRepository != null) {
|
||||
downloadConnection.binder?.enqueue(packageName, productRepository.first.name,
|
||||
productRepository.second, release)
|
||||
}
|
||||
|
||||
@@ -196,6 +196,12 @@ class ProductsAdapter(private val onClick: (ProductItem) -> Unit):
|
||||
}
|
||||
}
|
||||
|
||||
override fun areContentsTheSame(oldCursor: Cursor, newCursor: Cursor): Boolean {
|
||||
val oldItem = Database.ProductAdapter.transformItem(oldCursor)
|
||||
val newItem = Database.ProductAdapter.transformItem(newCursor)
|
||||
return oldItem == newItem
|
||||
}
|
||||
|
||||
@SuppressLint("NotifyDataSetChanged")
|
||||
override fun onCursorChanged(oldCursor: Cursor?, newCursor: Cursor?) {
|
||||
val oldSize = oldCursor?.count ?: 0
|
||||
|
||||
@@ -561,6 +561,7 @@ class TabsFragment: ScreenFragment() {
|
||||
|
||||
override fun setAlpha(alpha: Int) = Unit
|
||||
override fun setColorFilter(colorFilter: ColorFilter?) = Unit
|
||||
@Deprecated("Deprecated in Java")
|
||||
override fun getOpacity(): Int = PixelFormat.TRANSLUCENT
|
||||
}
|
||||
|
||||
|
||||
@@ -19,11 +19,11 @@ class Connection<B: IBinder, S: ConnectionService<B>>(private val serviceClass:
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
override fun onServiceConnected(componentName: ComponentName, binder: IBinder) {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
binder as B
|
||||
this.binder = binder
|
||||
onBind?.invoke(this, binder)
|
||||
val b = binder as B
|
||||
this.binder = b
|
||||
onBind?.invoke(this, b)
|
||||
}
|
||||
|
||||
override fun onServiceDisconnected(componentName: ComponentName) {
|
||||
|
||||
@@ -331,7 +331,7 @@ class SyncService: ConnectionService<SyncService.Binder>() {
|
||||
currentTask = null
|
||||
handleNextTask(false)
|
||||
val blocked = updateNotificationBlockerFragment?.get()?.isAdded == true
|
||||
if (!blocked && result != null && result.isNotEmpty()) {
|
||||
if (!blocked && !result.isNullOrEmpty()) {
|
||||
displayUpdatesNotification(result)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ import okhttp3.Response
|
||||
|
||||
object RxUtils {
|
||||
private class ManagedDisposable(private val cancel: () -> Unit): Disposable {
|
||||
@Volatile var disposed = false
|
||||
var disposed = false
|
||||
override fun isDisposed(): Boolean = disposed
|
||||
|
||||
override fun dispose() {
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package com.michatec.store.utility
|
||||
|
||||
import android.animation.ValueAnimator
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Context
|
||||
import android.content.pm.Signature
|
||||
import android.content.res.Configuration
|
||||
@@ -67,17 +66,11 @@ object Utils {
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressLint("SuspiciousIndentation")
|
||||
fun configureLocale(context: Context): Context {
|
||||
val supportedLanguages = BuildConfig.LANGUAGES.toSet()
|
||||
val configuration = context.resources.configuration
|
||||
val currentLocales = if (Android.sdk(24)) {
|
||||
val localesList = configuration.locales
|
||||
(0 until localesList.size()).map(localesList::get)
|
||||
} else {
|
||||
@Suppress("DEPRECATION")
|
||||
listOf(configuration.locale)
|
||||
}
|
||||
val localesList = configuration.locales
|
||||
val currentLocales = (0 until localesList.size()).map(localesList::get)
|
||||
val compatibleLocales = currentLocales
|
||||
.filter { it.language in supportedLanguages }
|
||||
.let { it.ifEmpty { listOf(Locale.US) } }
|
||||
|
||||
@@ -33,9 +33,8 @@ abstract class CursorRecyclerAdapter<VT: Enum<VT>, VH: RecyclerView.ViewHolder>:
|
||||
return
|
||||
}
|
||||
|
||||
// Further reduced threshold to 100 for DiffUtil to avoid any noticeable frame drops on the main thread.
|
||||
// JSON parsing and DB access during diffing are slow.
|
||||
if (oldSize > 100 || newSize > 100) {
|
||||
// Increased threshold for DiffUtil and optimized callback
|
||||
if (oldSize > 500 || newSize > 500) {
|
||||
notifyDataSetChanged()
|
||||
return
|
||||
}
|
||||
@@ -60,7 +59,6 @@ abstract class CursorRecyclerAdapter<VT: Enum<VT>, VH: RecyclerView.ViewHolder>:
|
||||
})
|
||||
diffResult.dispatchUpdatesTo(this)
|
||||
} catch (_: Exception) {
|
||||
// Fallback in case of cursor issues during diffing
|
||||
notifyDataSetChanged()
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user