安卓15所有应用列表 AllAppList.kt

安卓15所有应用列表 AllAppList.kt

实现 filter() 方法,该方法接收来自 AppListViewModel 的、已经经过“显示/隐藏系统应用”初步过滤的应用列表,然后根据 Spinner 的当前选定 option 来进一步筛选这些应用。

AppListPage.kt - 页面结构和选项菜单状态管理

// AppListPage.kt

@Composable

fun AppListPage(

// ...

listModel: AppListModel,

// ...

appList: @Composable AppListInput.() -> Unit = { AppList() },

) {

var showSystem by rememberSaveable { mutableStateOf(false) } // 选项菜单控制的状态

SearchScaffold(

title = title,

actions = {

if (!noMoreOptions) {

MoreOptionsAction { // 右上角三个点菜单

ShowSystemAction(showSystem) { showSystem = it } // 切换 showSystem 状态

moreOptions()

}

}

},

) { /* ... */

UserProfilePager { userGroup ->

val appListInput = AppListInput( // 将状态和模型打包

// ...

listModel = listModel, // 来自 AllAppList.kt

state = AppListState(

showSystem = { showSystem }, // 传递选项菜单的状态

searchQuery = searchQuery,

),

// ...

)

appList(appListInput) // 调用 AppList.kt 中的 AppList()

}

}

}

组成: AppListPage 创建了 showSystem 状态,并将其与 listModel (来自 AllAppList.kt) 打包到 AppListInput 中,传递给 AppList.kt。

AppList.kt - 连接 UI 和 ViewModel

// AppList.kt

@Composable

internal fun AppListInput.AppListImpl( // AppList() 会调用这个

viewModelSupplier: @Composable () -> IAppListViewModel,

) {

val viewModel = viewModelSupplier() // 获取 ViewModel 实例

Column {

val optionsState = viewModel.spinnerOptionsFlow.collectAsStateWithLifecycle(null)

SpinnerOptions(optionsState, viewModel.optionFlow) // 渲染 Spinner

val appListData = viewModel.appListDataFlow.collectAsStateWithLifecycle(null)

listModel.AppListWidget(appListData, /*...*/) // 渲染列表项, listModel 来自 AppListInput

}

}

@Composable

private fun rememberViewModel( // 创建或获取 ViewModel

config: AppListConfig,

listModel: AppListModel,

state: AppListState, // 接收来自 AppListPage 的 AppListInput.state

): AppListViewModel {

val viewModel: AppListViewModel = viewModel(key = config.userIds.toString())

// ...

viewModel.listModel.setIfAbsent(listModel) // 将 AllAppListModel 设给 ViewModel

viewModel.showSystem.Sync(state.showSystem) // **核心**: 同步选项菜单的 showSystem 状态到 ViewModel

viewModel.searchQuery.Sync(state.searchQuery) // 同步搜索词

// ...

return viewModel

}

组成: AppList.kt 从 AppListInput 中获取 state 和 listModel。它初始化 AppListViewModel,并将 state.showSystem 和 listModel (即 AllAppListModel) 设置给 ViewModel。然后它观察 ViewModel 的数据流来更新 UI。

AppListViewModel.kt - 核心过滤逻辑

// AppListViewModel.kt (内部类 UserSubGraph)

private inner class UserSubGraph(/* ... */) {

// ...

val recordListFlow = listModel.flow // listModel 是 AllAppListModel

.flatMapLatest { it.transform(userIdFlow, appsStateFlow.filterNotNull()) }

// ...

private val systemFilteredFlow = // **第一层过滤:基于选项菜单的 showSystem**

appListRepository.showSystemPredicate(userIdFlow, this@AppListViewModelImpl.showSystem.flow) // this.showSystem 来自 AppList.kt 同步过来的选项菜单状态

.combine(recordListFlow) { showAppPredicate, recordList ->

// --- Logging modification by AI Assistant --- (这是我们加的,可以忽略)

println("[AppListViewModel][systemFilteredFlow] OptionsMenu showSystem state: ${this@AppListViewModelImpl.showSystem.flow.value}") // 示例日志

// --------------------------------------------

recordList.filter { record -> // 对原始列表进行过滤

val appInfo = record.app

// 对于通用流程,这里是:

showAppPredicate(appInfo) // 使用 AppListRepository 提供的标准谓词

}

}

// ...

val listModelFilteredFlow = optionFlow.filterNotNull().flatMapLatest { option -> // option 是 Spinner 的当前选项

listModel.flow.flatMapLatest { listModel -> // listModel 是 AllAppListModel

// **第二层过滤:基于 Spinner 选项**

listModel.filter(this.userIdFlow, option, this.systemFilteredFlow) // 调用 AllAppListModel.filter,传入上一阶段已过滤的 systemFilteredFlow

}

}

// ...

}

// ViewModel 主类中

override val appListDataFlow = // 最终暴露给 UI 的数据流

combine(

appEntryListFlow, // 它基于 listModelFilteredFlow (已包含两层过滤)

// ...

) { /* ... */ }

.combine(searchQuery.flow) { appListData, searchQuery -> // **第三层过滤:基于搜索词**

appListData.filter {

it.label.contains(other = searchQuery, ignoreCase = true)

}

}

// ...

组成: AppListViewModel 接收同步过来的 showSystem 状态。在 systemFilteredFlow 中,它使用这个状态和 AppListRepository 的逻辑进行第一次过滤。然后,它将这个结果 (systemFilteredFlow) 和当前的 Spinner option 传递给 listModel.filter() (即 AllAppListModel.filter) 进行第二次过滤。最后,应用搜索词过滤。

AllAppList.kt - 定义 Spinner 行为

// AllAppList.kt (class AllAppListModel)

override fun filter(

userIdFlow: Flow,

option: Int, // 当前 Spinner 选项

recordListFlow: Flow>, // **注意**: 这里的 recordListFlow 是 AppListViewModel 中已经经过 systemFilteredFlow 处理的列表

): Flow> = recordListFlow.filterItem { record ->

val app = record.app

val selectedOption = SpinnerItem.entries.getOrNull(option)

// --- Logging modification by AI Assistant --- (这是我们加的,可以忽略)

// println("[AllAppListFilter-Reverted] Processing app: ${app.packageName}, Spinner Option: $selectedOption")

// --------------------------------------------

// 只根据 Spinner 选项进行基本过滤

when (selectedOption) {

SpinnerItem.Enabled -> app.enabled && !app.isInstantApp

SpinnerItem.Disabled -> isDisabled(record)

SpinnerItem.Instant -> isInstant(record)

else -> true // 包括 SpinnerItem.All (全部应用)

}

}

组成: AllAppListModel 的 filter 方法接收 AppListViewModel 传递过来的、已经根据“选项菜单”状态过滤过的应用列表。然后,它纯粹根据当前的 Spinner 选项 (option) 对这个列表执行进一步的筛选。

总结:

这四个文件形成了一个清晰的分层结构:

相关推荐

《王者荣耀》朱雀对应哪个英雄 朱雀对应英雄介绍
beat365在线体育正规吗

《王者荣耀》朱雀对应哪个英雄 朱雀对应英雄介绍

⌛ 07-15 👁️ 6531
什么是棍刑 古代十大酷刑之一(受刑让人苦不堪言)
beat365下载唯一官方网

什么是棍刑 古代十大酷刑之一(受刑让人苦不堪言)

⌛ 08-21 👁️ 2933