Skip to content

Commit ebb3ece

Browse files
refactor(AppDrawerAdapter): Improve performance and readability
This commit refactors the `bind()` method within the `AppDrawerViewHolder` for better performance, clarity, and reduced complexity. Key changes include: - **Reduced Redundancy**: Pre-calculating `isLocked`, `isPinned`, and `isHidden` states to avoid repeated lookups. - **Improved Readability**: The `bind` method is now structured with numbered and commented sections, making the logic easier to follow. - **Simplified Conditionals**: Replaced multiple `if/else` statements with more concise `when` blocks or ternary operators for setting text and drawables. - **Optimized Icon Loading**: The icon loading logic is streamlined to set a placeholder immediately and then load the actual icon asynchronously only if it's not already cached. - **Conditional Logging**: In both `AppDrawerAdapter` and `ContactDrawerAdapter`, logging of the search query now only occurs if the query is not empty, preventing unnecessary log entries.
1 parent 354b0ce commit ebb3ece

File tree

2 files changed

+113
-185
lines changed

2 files changed

+113
-185
lines changed

app/src/main/java/com/github/droidworksstudio/mlauncher/ui/adapter/AppDrawerAdapter.kt

Lines changed: 112 additions & 184 deletions
Original file line numberDiff line numberDiff line change
@@ -233,7 +233,7 @@ class AppDrawerAdapter(
233233
filtered.toMutableList()
234234
}
235235

236-
AppLogger.d("searchQuery", query)
236+
if (query.isNotEmpty()) AppLogger.d("searchQuery", query)
237237

238238
val filterResults = FilterResults()
239239
filterResults.values = filteredApps
@@ -333,258 +333,186 @@ class AppDrawerAdapter(
333333
iconLoadingScope: CoroutineScope,
334334
prefs: Prefs
335335
) = with(itemView) {
336+
336337
val contextMenuFlags = prefs.getMenuFlags("CONTEXT_MENU_FLAGS", "0011111")
338+
339+
// ----------------------------
340+
// 1️⃣ Hide optional layouts
337341
appHideLayout.isVisible = false
338342
appRenameLayout.isVisible = false
339343
appTagLayout.isVisible = false
340344

341-
appHide.apply {
342-
isVisible = contextMenuFlags[2]
343-
// set show/hide icon
344-
if (flag == AppDrawerFlag.HiddenApps) {
345-
setCompoundDrawablesWithIntrinsicBounds(0, R.drawable.visibility, 0, 0)
346-
text = getLocalizedString(R.string.show)
347-
} else {
348-
setCompoundDrawablesWithIntrinsicBounds(0, R.drawable.visibility_off, 0, 0)
349-
text = getLocalizedString(R.string.hide)
350-
}
351-
}
345+
val packageName = appListItem.activityPackage
352346

353-
val appName = appListItem.activityPackage
354-
// Access the current locked apps set
355-
val currentLockedApps = prefs.lockedApps
347+
// ----------------------------
348+
// 2️⃣ Precompute lock/pin/hide state
349+
val isLocked = prefs.lockedApps.contains(packageName)
350+
val isPinned = prefs.pinnedApps.contains(packageName)
351+
val isHidden = (flag == AppDrawerFlag.HiddenApps)
356352

353+
// ----------------------------
354+
// 3️⃣ Setup lock/pin/hide buttons
357355
appLock.apply {
358356
isVisible = contextMenuFlags[1]
359-
if (currentLockedApps.contains(appName)) {
360-
setCompoundDrawablesWithIntrinsicBounds(0, R.drawable.padlock, 0, 0)
361-
text = getLocalizedString(R.string.unlock)
362-
} else {
363-
setCompoundDrawablesWithIntrinsicBounds(0, R.drawable.padlock_off, 0, 0)
364-
text = getLocalizedString(R.string.lock)
365-
}
357+
setCompoundDrawablesWithIntrinsicBounds(
358+
0,
359+
if (isLocked) R.drawable.padlock else R.drawable.padlock_off,
360+
0,
361+
0
362+
)
363+
text = if (isLocked) getLocalizedString(R.string.unlock) else getLocalizedString(R.string.lock)
366364
}
367365

368-
val currentPinnedApps = prefs.pinnedApps
369-
370366
appPin.apply {
371367
isVisible = contextMenuFlags[0]
372-
if (currentPinnedApps.contains(appName)) {
373-
setCompoundDrawablesWithIntrinsicBounds(0, R.drawable.pin, 0, 0)
374-
text = getLocalizedString(R.string.unpin)
375-
} else {
376-
setCompoundDrawablesWithIntrinsicBounds(0, R.drawable.pin_off, 0, 0)
377-
text = getLocalizedString(R.string.pin)
378-
}
368+
setCompoundDrawablesWithIntrinsicBounds(
369+
0,
370+
if (isPinned) R.drawable.pin else R.drawable.pin_off,
371+
0,
372+
0
373+
)
374+
text = if (isPinned) getLocalizedString(R.string.unpin) else getLocalizedString(R.string.pin)
379375
}
380376

377+
appHide.apply {
378+
isVisible = contextMenuFlags[2]
379+
setCompoundDrawablesWithIntrinsicBounds(
380+
0,
381+
if (isHidden) R.drawable.visibility else R.drawable.visibility_off,
382+
0,
383+
0
384+
)
385+
text = if (isHidden) getLocalizedString(R.string.show) else getLocalizedString(R.string.hide)
386+
}
387+
388+
// ----------------------------
389+
// 4️⃣ Setup rename/tag layouts
381390
appRename.apply {
382391
isVisible = contextMenuFlags[3]
383392
setOnClickListener {
384-
if (appListItem.activityPackage.isNotEmpty()) {
385-
appRenameEdit.hint = appListItem.activityLabel
386-
appRenameLayout.isVisible = true
387-
appHideLayout.isVisible = false
388-
appRenameEdit.showKeyboard()
389-
appRenameEdit.imeOptions = EditorInfo.IME_ACTION_DONE
390-
}
393+
appRenameEdit.hint = appListItem.activityLabel
394+
appRenameLayout.isVisible = true
395+
appHideLayout.isVisible = false
396+
appRenameEdit.showKeyboard()
397+
appRenameEdit.imeOptions = EditorInfo.IME_ACTION_DONE
391398
}
392399
}
393400

394401
appTag.apply {
395402
isVisible = contextMenuFlags[4]
396403
setOnClickListener {
397-
if (appListItem.activityPackage.isNotEmpty()) {
398-
appTagEdit.hint = appListItem.activityLabel
399-
appTagLayout.isVisible = true
400-
appHideLayout.isVisible = false
401-
appTagEdit.showKeyboard()
402-
appTagEdit.imeOptions = EditorInfo.IME_ACTION_DONE
403-
}
404+
appTagEdit.hint = appListItem.activityLabel
405+
appTagLayout.isVisible = true
406+
appHideLayout.isVisible = false
407+
appTagEdit.showKeyboard()
408+
appTagEdit.imeOptions = EditorInfo.IME_ACTION_DONE
404409
}
405410
}
406411

407412
appRenameEdit.apply {
413+
text = Editable.Factory.getInstance().newEditable(appListItem.label)
408414
addTextChangedListener(object : TextWatcher {
409-
410415
override fun afterTextChanged(s: Editable) {}
411-
412-
override fun beforeTextChanged(
413-
s: CharSequence, start: Int,
414-
count: Int, after: Int
415-
) {
416-
}
417-
418-
override fun onTextChanged(
419-
s: CharSequence, start: Int,
420-
before: Int, count: Int
421-
) {
422-
if (appRenameEdit.text.isEmpty()) {
423-
appSaveRename.text = getLocalizedString(R.string.reset)
424-
} else if (appRenameEdit.text.toString() == appListItem.customLabel) {
425-
appSaveRename.text = getLocalizedString(R.string.cancel)
426-
} else {
427-
appSaveRename.text = getLocalizedString(R.string.rename)
416+
override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {}
417+
override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {
418+
appSaveRename.text = when {
419+
text.isEmpty() -> getLocalizedString(R.string.reset)
420+
text.toString() == appListItem.customLabel -> getLocalizedString(R.string.cancel)
421+
else -> getLocalizedString(R.string.rename)
428422
}
429423
}
430424
})
431-
// set current name as default text in EditText
432-
text = Editable.Factory.getInstance().newEditable(appListItem.label)
433425
}
434426

435427
appTagEdit.apply {
428+
text = Editable.Factory.getInstance().newEditable(appListItem.customTag)
436429
addTextChangedListener(object : TextWatcher {
437-
438430
override fun afterTextChanged(s: Editable) {}
439-
440-
override fun beforeTextChanged(
441-
s: CharSequence, start: Int,
442-
count: Int, after: Int
443-
) {
444-
}
445-
446-
override fun onTextChanged(
447-
s: CharSequence, start: Int,
448-
before: Int, count: Int
449-
) {
450-
if (appTagEdit.text.toString() == appListItem.customTag) {
451-
appSaveTag.text = getLocalizedString(R.string.cancel)
452-
} else {
453-
appSaveTag.text = getLocalizedString(R.string.tag)
454-
}
431+
override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {}
432+
override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {
433+
appSaveTag.text = if (text.toString() == appListItem.customTag) getLocalizedString(R.string.cancel)
434+
else getLocalizedString(R.string.tag)
455435
}
456436
})
457-
// set current name as default text in EditText
458-
text = Editable.Factory.getInstance().newEditable(appListItem.customTag)
459437
}
460438

461-
appTitle.text = appListItem.label
439+
appClose.setOnClickListener {
440+
appHideLayout.isVisible = false
441+
visibleHideLayouts.remove(absoluteAdapterPosition)
442+
val sidebarContainer = (context as? Activity)?.findViewById<View>(R.id.sidebar_container)
443+
if (visibleHideLayouts.isEmpty()) sidebarContainer?.isVisible = prefs.showAZSidebar
444+
}
462445

463-
// set text gravity
446+
// ----------------------------
447+
// 5️⃣ App title
448+
appTitle.text = appListItem.label
464449
val params = appTitle.layoutParams as FrameLayout.LayoutParams
465450
params.gravity = appLabelGravity
466451
appTitle.layoutParams = params
452+
val padding = dp2px(resources, 24)
453+
appTitle.updatePadding(left = padding, right = padding)
467454

468-
// add icon next to app name to indicate that this app is installed on another profile
469-
val packageName = appListItem.activityPackage
470-
471-
// Use a placeholder icon
455+
// ----------------------------
456+
// 6️⃣ Icon loading off main thread
472457
val placeholderIcon = AppCompatResources.getDrawable(context, R.drawable.ic_default_app)
473-
474-
// Add work profile or private space icon if needed
475-
if (packageName.isNotBlank() && prefs.iconPackAppList != Constants.IconPacks.Disabled) {
476-
// Try to get from cache first
477-
val cachedIcon = iconCache[packageName]
478-
if (cachedIcon != null) {
479-
// Use cached icon
480-
setAppTitleIcon(appTitle, cachedIcon, prefs)
481-
} else {
482-
// Set placeholder immediately
483-
setAppTitleIcon(appTitle, placeholderIcon, prefs)
484-
// Load icon asynchronously
485-
iconLoadingScope.launch {
486-
val icon = withContext(Dispatchers.IO) {
487-
// Get icon as before
488-
val iconPackPackage = prefs.customIconPackAppList
489-
val iconPackage = IconCacheTarget.APP_LIST
490-
val nonNullDrawable: Drawable = getSafeAppIcon(
491-
context = context,
492-
packageName = packageName,
493-
useIconPack = (iconPackPackage.isNotEmpty() && prefs.iconPackAppList == Constants.IconPacks.Custom),
494-
iconPackTarget = iconPackage
495-
)
496-
getSystemIcons(
497-
context,
498-
prefs,
499-
iconPackage,
500-
nonNullDrawable
501-
) ?: nonNullDrawable
502-
}
503-
iconCache[packageName] = icon
504-
// Only update if still bound to this app
505-
if (appTitle.text == appListItem.label) {
506-
setAppTitleIcon(appTitle, icon, prefs)
507-
}
458+
val cachedIcon = iconCache[packageName]
459+
setAppTitleIcon(appTitle, cachedIcon ?: placeholderIcon, prefs)
460+
461+
if (cachedIcon == null && packageName.isNotBlank() && prefs.iconPackAppList != Constants.IconPacks.Disabled) {
462+
iconLoadingScope.launch {
463+
val icon = withContext(Dispatchers.IO) {
464+
val nonNullDrawable: Drawable = getSafeAppIcon(
465+
context = context,
466+
packageName = packageName,
467+
useIconPack = prefs.customIconPackAppList.isNotEmpty() &&
468+
prefs.iconPackAppList == Constants.IconPacks.Custom,
469+
iconPackTarget = IconCacheTarget.APP_LIST
470+
)
471+
getSystemIcons(context, prefs, IconCacheTarget.APP_LIST, nonNullDrawable) ?: nonNullDrawable
508472
}
473+
iconCache[packageName] = icon
474+
if (appTitle.text == appListItem.label) setAppTitleIcon(appTitle, icon, prefs)
509475
}
510476
}
511477

512-
513-
val padding = dp2px(resources, 24)
514-
appTitle.updatePadding(left = padding, right = padding)
515-
516-
val sidebarContainer = (context as Activity).findViewById<View>(R.id.sidebar_container)
517-
478+
// ----------------------------
479+
// 7️⃣ Click listeners
480+
val sidebarContainer = (context as? Activity)?.findViewById<View>(R.id.sidebar_container)
518481
appTitleFrame.apply {
519-
setOnClickListener {
520-
appClickListener(appListItem)
521-
}
482+
setOnClickListener { appClickListener(appListItem) }
522483
setOnLongClickListener {
523-
val openApp =
524-
flag == AppDrawerFlag.LaunchApp || flag == AppDrawerFlag.HiddenApps
484+
val openApp = flag == AppDrawerFlag.LaunchApp || flag == AppDrawerFlag.HiddenApps
525485
if (openApp) {
526486
try {
527-
appDelete.alpha =
528-
if (context.isSystemApp(appListItem.activityPackage)) 0.3f else 1.0f
487+
appDelete.alpha = if (context.isSystemApp(packageName)) 0.3f else 1f
529488
appHideLayout.isVisible = true
530-
sidebarContainer.isVisible = false
489+
sidebarContainer?.isVisible = false
531490
visibleHideLayouts.add(absoluteAdapterPosition)
532-
} catch (e: Exception) {
533-
e.printStackTrace()
491+
} catch (_: Exception) {
534492
}
535493
}
536494
true
537495
}
538496
}
539497

540-
appInfo.apply {
541-
isVisible = contextMenuFlags[5]
542-
setOnClickListener {
543-
appInfoListener(appListItem)
544-
}
545-
}
546-
547-
appDelete.apply {
548-
isVisible = contextMenuFlags[6]
549-
setOnClickListener {
550-
appDeleteListener(appListItem)
551-
}
552-
}
498+
appInfo.setOnClickListener { appInfoListener(appListItem) }
499+
appDelete.setOnClickListener { appDeleteListener(appListItem) }
553500

554-
appClose.apply {
555-
setOnClickListener {
556-
appHideLayout.isVisible = false
557-
visibleHideLayouts.remove(absoluteAdapterPosition)
558-
if (visibleHideLayouts.isEmpty()) {
559-
sidebarContainer.isVisible = prefs.showAZSidebar
560-
}
561-
}
501+
// ----------------------------
502+
// 8️⃣ Lock/Pin toggle actions
503+
appLock.setOnClickListener {
504+
val updated = prefs.lockedApps.toMutableSet()
505+
if (isLocked) updated.remove(packageName) else updated.add(packageName)
506+
prefs.lockedApps = updated
562507
}
563-
564-
appPin.apply {
565-
setOnClickListener {
566-
val appName = appListItem.activityPackage
567-
val updatedPinnedApps = prefs.pinnedApps.toMutableSet()
568-
569-
val isPinned = updatedPinnedApps.contains(appName)
570-
AppLogger.d("AppListDebug", if (isPinned) "📌 Unpinning $appName" else "📌 Pinning $appName")
571-
572-
if (isPinned) {
573-
updatedPinnedApps.remove(appName)
574-
appPin.setCompoundDrawablesWithIntrinsicBounds(0, R.drawable.pin_off, 0, 0)
575-
appPin.text = getLocalizedString(R.string.pin)
576-
} else {
577-
updatedPinnedApps.add(appName)
578-
appPin.setCompoundDrawablesWithIntrinsicBounds(0, R.drawable.pin, 0, 0)
579-
appPin.text = getLocalizedString(R.string.unpin)
580-
}
581-
582-
prefs.pinnedApps = updatedPinnedApps.toSet()
583-
AppLogger.d("AppListDebug", "✅ Updated pinnedApps: ${prefs.pinnedApps}")
584-
}
508+
appPin.setOnClickListener {
509+
val updated = prefs.pinnedApps.toMutableSet()
510+
if (isPinned) updated.remove(packageName) else updated.add(packageName)
511+
prefs.pinnedApps = updated
585512
}
586513
}
587514

515+
588516
// Helper to set icon on appTitle with correct size and alignment
589517
private fun setAppTitleIcon(appTitle: TextView, icon: Drawable?, prefs: Prefs) {
590518
if (icon == null) {

app/src/main/java/com/github/droidworksstudio/mlauncher/ui/adapter/ContactDrawerAdapter.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ class ContactDrawerAdapter(
101101
}
102102
}
103103

104-
AppLogger.d("searchQuery", searchChars)
104+
if (searchChars.isNotEmpty()) AppLogger.d("searchQuery", searchChars)
105105

106106
val filterResults = FilterResults()
107107
filterResults.values = filteredContacts

0 commit comments

Comments
 (0)