Jetpack Compose:如何减少Composable函数的参数数量(整洁代码)
解决Composable参数过多的几种方案
1. 把相关参数封装成数据类
将状态数据和交互回调分别打包成独立的数据类,大幅减少外部传递的参数数量:
// 封装所有需要展示的状态 data class TopSectionState( val filterParametersState: FilterParametersState, val itineraryCount: Int, val buttonNames: List<String>, val buttonNamesFilters: List<String>, val selectedButtonIndex: Int, val selectedButtonName: String, val isThemeSwitchChecked: Boolean, val selectedSort: String ) // 封装所有交互回调 data class TopSectionActions( val updateSelectedSort: (String) -> Unit, val getLocation: (String) -> Unit, val updateFlightSearchDepartureTime: (Date) -> Unit, val updateFlightSearchCityDeparture: () -> Unit, val updateFlightSearchCityArrival: () -> Unit, val updateFlightSearchPassengersCount: (Int) -> Unit, val onDisableNextDayArrivalsClicked: (Boolean) -> Unit, val onDurationButtonClicked: (String) -> Unit, val onThemeSwitchClicked: () -> Unit, val onSliderValueChange: (Float) -> Unit, val onParamsUpperClicked: (Int, String) -> Unit, val onParamsBottomClicked: (String) -> Unit )
调用时只需传递两个参数:
TopSection( state = TopSectionState( filterParametersState = filterParametersState, itineraryCount = flightsFromApiResponse.result?.itineraryCount ?: 0, buttonNames = viewModel.buttonNames, buttonNamesFilters = viewModel.buttonNamesFilters, selectedButtonIndex = viewModel.selectedButtonIndex.value, selectedButtonName = viewModel.selectedButtonName.value, isThemeSwitchChecked = themeViewModel.isDarkTheme, selectedSort = viewModel.selectedSort.value ), actions = TopSectionActions( updateSelectedSort = { viewModel.updateSelectedSort(it) }, getLocation = { viewModel.getLocation(it) }, updateFlightSearchDepartureTime = { viewModel.updateFlightSearchDepartureTime(it) }, updateFlightSearchCityDeparture = { viewModel.updateFlightSearchCityDeparture(viewModel.location.value.cityCode ?: "WAR") }, updateFlightSearchCityArrival = { viewModel.updateFlightSearchCityArrival(viewModel.location.value.cityCode ?: "PAR") }, updateFlightSearchPassengersCount = { viewModel.updateFlightSearchPassengersCount(it) }, onDisableNextDayArrivalsClicked = { viewModel.updateFilterDisableNextDayArrivals(it) }, onDurationButtonClicked = { viewModel.updateFilterMaxDuration(it) }, onThemeSwitchClicked = { themeViewModel.switchTheme() }, onSliderValueChange = { viewModel.updateFilterMaxPrice(it) }, onParamsUpperClicked = { index, name -> viewModel.updateSelectedButtonIndex(index) viewModel.updateSelectedButtonName(name) }, onParamsBottomClicked = { buttonName -> if (buttonName != "SAVE") { viewModel.updateSelectedButtonName(buttonName) } else { commonViewModel.updateCurrentFlightParams(flightSearchParametersState) viewModel.getFlights() } } ) )
2. 在TopSection内部直接获取ViewModel
既然TopSection是HomeScreen专属的功能区域,无需从外部传递ViewModel的所有状态和回调,直接在Composable内部获取对应ViewModel即可:
@Composable fun TopSection( flightSearchParametersState: FlightSearchParametersState, flightsFromApiResponse: ApiResponse<FlightResult> ) { val homeViewModel: HomeViewModel = viewModel() val themeViewModel: ThemeViewModel = viewModel() val commonViewModel: CommonViewModel = viewModel() // 直接从ViewModel获取所需状态 val itineraryCount = flightsFromApiResponse.result?.itineraryCount ?: 0 val selectedButtonIndex = homeViewModel.selectedButtonIndex.value val selectedButtonName = homeViewModel.selectedButtonName.value // ... 其他状态直接从对应ViewModel读取 // 交互逻辑直接调用ViewModel方法 val onThemeSwitchClicked = { themeViewModel.switchTheme() } val updateSelectedSort = { sortName: String -> homeViewModel.updateSelectedSort(sortName) } // ... 其他回调内部定义 // 原有TopSection的UI实现代码 }
外部调用会极度简化:
TopSection( flightSearchParametersState = flightSearchParametersState, flightsFromApiResponse = flightsFromApiResponse )
3. 合并重复逻辑的回调
观察代码中的重复逻辑,将相似的回调合并成一个。比如updateFlightSearchCityDeparture和updateFlightSearchCityArrival都是基于location.value.cityCode的操作,可以在ViewModel中封装统一方法:
// 在HomeViewModel中新增方法 fun updateFlightCity(isDeparture: Boolean, defaultCityCode: String) { val cityCode = location.value.cityCode ?: defaultCityCode if (isDeparture) { updateFlightSearchCityDeparture(cityCode) } else { updateFlightSearchCityArrival(cityCode) } }
外部只需传递一个回调:
updateFlightCity = { isDeparture, default -> viewModel.updateFlightCity(isDeparture, default) }
以此减少不必要的参数传递。
内容的提问来源于stack exchange,提问作者deja
相关产品推荐
相关产品推荐

