From f46cdad05d685b77f451c3c241efb4818a741ddb Mon Sep 17 00:00:00 2001 From: Chaohui Wang Date: Tue, 28 Feb 2023 19:37:55 +0800 Subject: [PATCH] Fix App Info item summaries not refreshed On tablet, "Open by default" & default app shortcut not refreshed when settings changed. Changing from liveData to flow fix this issue on tablet. Bug: 236346018 Test: Manually with App Info Change-Id: I6e3a174bdbecb154e39e111ecf695b1146c484df --- .../app/appinfo/AppOpenByDefaultPreference.kt | 27 +++++++++++-------- .../appinfo/DefaultAppShortcutPreference.kt | 27 ++++++++++++------- 2 files changed, 33 insertions(+), 21 deletions(-) diff --git a/src/com/android/settings/spa/app/appinfo/AppOpenByDefaultPreference.kt b/src/com/android/settings/spa/app/appinfo/AppOpenByDefaultPreference.kt index 4cc24b36a87..2c98e08f739 100644 --- a/src/com/android/settings/spa/app/appinfo/AppOpenByDefaultPreference.kt +++ b/src/com/android/settings/spa/app/appinfo/AppOpenByDefaultPreference.kt @@ -19,11 +19,11 @@ package com.android.settings.spa.app.appinfo import android.content.Context import android.content.pm.ApplicationInfo import androidx.compose.runtime.Composable -import androidx.compose.runtime.livedata.observeAsState import androidx.compose.runtime.remember import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.stringResource -import androidx.lifecycle.liveData +import androidx.lifecycle.compose.ExperimentalLifecycleComposeApi +import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.android.settings.R import com.android.settings.applications.appinfo.AppInfoDashboardFragment import com.android.settings.applications.intentpicker.AppLaunchSettings @@ -38,17 +38,20 @@ import com.android.settingslib.spaprivileged.model.app.hasFlag import com.android.settingslib.spaprivileged.model.app.userHandle import com.android.settingslib.spaprivileged.model.app.userId import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.flow.flow +import kotlinx.coroutines.flow.flowOn +@OptIn(ExperimentalLifecycleComposeApi::class) @Composable fun AppOpenByDefaultPreference(app: ApplicationInfo) { val context = LocalContext.current - val presenter = remember { AppOpenByDefaultPresenter(context, app) } - if (!presenter.isAvailable()) return + val presenter = remember(app) { AppOpenByDefaultPresenter(context, app) } + if (remember(presenter) { !presenter.isAvailable() }) return Preference(object : PreferenceModel { override val title = stringResource(R.string.launch_by_default) - override val summary = presenter.summaryLiveData.observeAsState( - initial = stringResource(R.string.summary_placeholder), + override val summary = presenter.summaryFlow.collectAsStateWithLifecycle( + initialValue = stringResource(R.string.summary_placeholder), ) override val enabled = stateOf(presenter.isEnabled()) override val onClick = presenter::startActivity @@ -66,14 +69,16 @@ private class AppOpenByDefaultPresenter( fun isEnabled() = app.hasFlag(ApplicationInfo.FLAG_INSTALLED) && app.enabled - val summaryLiveData = liveData(Dispatchers.IO) { - emit(context.getString(when { + val summaryFlow = flow { emit(getSummary()) }.flowOn(Dispatchers.IO) + + private fun getSummary() = context.getString( + when { isLinkHandlingAllowed() -> R.string.app_link_open_always else -> R.string.app_link_open_never - })) - } + } + ) - fun isLinkHandlingAllowed(): Boolean { + private fun isLinkHandlingAllowed(): Boolean { val userState = IntentPickerUtils.getDomainVerificationUserState( domainVerificationManager, app.packageName ) diff --git a/src/com/android/settings/spa/app/appinfo/DefaultAppShortcutPreference.kt b/src/com/android/settings/spa/app/appinfo/DefaultAppShortcutPreference.kt index 7b0de92b3e3..fa7e089cb09 100644 --- a/src/com/android/settings/spa/app/appinfo/DefaultAppShortcutPreference.kt +++ b/src/com/android/settings/spa/app/appinfo/DefaultAppShortcutPreference.kt @@ -26,6 +26,8 @@ import androidx.compose.runtime.livedata.observeAsState import androidx.compose.runtime.remember import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.stringResource +import androidx.lifecycle.compose.ExperimentalLifecycleComposeApi +import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.lifecycle.liveData import com.android.settings.R import com.android.settingslib.spa.widget.preference.Preference @@ -39,23 +41,28 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.asExecutor import kotlinx.coroutines.async import kotlinx.coroutines.coroutineScope +import kotlinx.coroutines.flow.flow +import kotlinx.coroutines.flow.flowOn data class DefaultAppShortcut( val roleName: String, @StringRes val titleResId: Int, ) +@OptIn(ExperimentalLifecycleComposeApi::class) @Composable fun DefaultAppShortcutPreference(shortcut: DefaultAppShortcut, app: ApplicationInfo) { val context = LocalContext.current - val presenter = remember { DefaultAppShortcutPresenter(context, shortcut.roleName, app) } - if (!presenter.isAvailable()) return + val presenter = remember(shortcut.roleName, app) { + DefaultAppShortcutPresenter(context, shortcut.roleName, app) + } + if (remember(presenter) { !presenter.isAvailable() }) return if (presenter.isVisible().observeAsState().value != true) return Preference(object : PreferenceModel { override val title = stringResource(shortcut.titleResId) - override val summary = presenter.summaryLiveData.observeAsState( - initial = stringResource(R.string.summary_placeholder), + override val summary = presenter.summaryFlow.collectAsStateWithLifecycle( + initialValue = stringResource(R.string.summary_placeholder), ) override val onClick = presenter::startActivity }) @@ -93,13 +100,13 @@ private class DefaultAppShortcutPresenter( } } - val summaryLiveData = liveData(Dispatchers.IO) { - val defaultApp = roleManager.getRoleHoldersAsUser(roleName, app.userHandle).firstOrNull() + val summaryFlow = flow { emit(getSummary()) }.flowOn(Dispatchers.IO) - emit(context.getString(when (defaultApp) { - app.packageName -> R.string.yes - else -> R.string.no - })) + private fun getSummary(): String { + val defaultApp = roleManager.getRoleHoldersAsUser(roleName, app.userHandle).firstOrNull() + return context.getString( + if (defaultApp == app.packageName) R.string.yes else R.string.no + ) } fun startActivity() {