Jetpack Compose电商应用:复杂筛选系统与Deep Link集成咨询
Jetpack Compose电商筛选系统:两屏通信+Deep Link实现方案
一、替换共享ViewModel,用可序列化状态实现屏幕通信
之前共享ViewModel的问题是Deep Link无法直接初始化筛选状态,所以先把筛选条件抽象成可序列化的数据类,作为屏幕间传递和Deep Link解析的核心:
- 定义
FilterParams数据类,实现Parcelable(性能优于Serializable):
@Parcelize data class FilterParams( val minPrice: Double? = null, val maxPrice: Double? = null, val categoryId: String? = null, val condition: String? = null, val brandId: String? = null ) : Parcelable
- 屏幕间通信改用Compose Navigation参数传递:
- 商品列表页(Screen A)跳转到筛选页(Screen B)时,将当前筛选条件编码后传入:
// Screen A跳转逻辑 navController.navigate( "filter_screen/${Uri.encode(Json.encodeToString(currentFilter))}" )- 筛选页(Screen B)接收参数,调整完成后将更新后的条件回传给上一页面:
// Screen B返回逻辑 navController.previousBackStackEntry?.savedStateHandle?.set( "updated_filter", updatedFilter ) navController.popBackStack()- 商品列表页(Screen A)监听返回的更新条件,触发数据刷新:
// Screen A添加监听逻辑 LaunchedEffect(Unit) { navController.currentBackStackEntry?.savedStateHandle?.getLiveData<FilterParams>("updated_filter")?.observe(this) { newFilter -> viewModel.fetchProducts(newFilter) } }
二、Deep Link集成实现步骤
1. 配置导航路由的Deep Link规则
在NavGraph中为商品列表页(Screen A)添加Deep Link路由,将筛选参数设为可选占位符:
navGraphBuilder.composable( route = "product_list?minPrice={minPrice}&maxPrice={maxPrice}&categoryId={categoryId}&condition={condition}&brandId={brandId}", deepLinks = listOf( navDeepLink { uriPattern = "your_app_scheme://product_list?minPrice={minPrice}&maxPrice={maxPrice}&categoryId={categoryId}&condition={condition}&brandId={brandId}" } ) ) { backStackEntry -> // 解析Deep Link参数,组装成FilterParams val filterParams = FilterParams( minPrice = backStackEntry.arguments?.getString("minPrice")?.toDoubleOrNull(), maxPrice = backStackEntry.arguments?.getString("maxPrice")?.toDoubleOrNull(), categoryId = backStackEntry.arguments?.getString("categoryId"), condition = backStackEntry.arguments?.getString("condition"), brandId = backStackEntry.arguments?.getString("brandId") ) ProductListScreen(filterParams = filterParams) }
2. 统一筛选请求逻辑
不管是Deep Link传入的条件还是筛选页返回的更新条件,都通过ViewModel的同一个方法触发Retrofit请求:
@HiltViewModel class ProductListViewModel @Inject constructor( private val productRepo: ProductRepository ) : ViewModel() { private val _products = MutableStateFlow<List<Product>>(emptyList()) val products = _products.asStateFlow() fun fetchProducts(filterParams: FilterParams) { viewModelScope.launch { val response = productRepo.getProducts(filterParams) _products.value = response.body() ?: emptyList() } } }
Screen A初始化时,若存在Deep Link传入的FilterParams则直接请求,否则用默认空参数加载全部商品。
3. 配置Manifest唤起应用
在AndroidManifest.xml的MainActivity中添加intent-filter,让系统能识别并唤起你的Deep Link:
<activity android:name=".MainActivity" android:exported="true"> <intent-filter> <action android:name="android.intent.action.VIEW" /> <category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.BROWSABLE" /> <data android:scheme="your_app_scheme" android:host="product_list" /> </intent-filter> </activity>
三、额外优化点
- 给
FilterParams所有字段设置默认值,避免Deep Link参数缺失导致空指针。 - 筛选页(Screen B)接收Screen A传入的初始条件,自动填充到筛选控件中,保持状态连贯性。
- 封装Deep Link参数解析扩展函数,简化代码:
fun NavBackStackEntry.parseFilterParams(): FilterParams { return FilterParams( minPrice = arguments?.getString("minPrice")?.toDoubleOrNull(), maxPrice = arguments?.getString("maxPrice")?.toDoubleOrNull(), categoryId = arguments?.getString("categoryId"), condition = arguments?.getString("condition"), brandId = arguments?.getString("brandId") ) }
内容的提问来源于stack exchange,提问作者Wojtek W
相关产品推荐
相关产品推荐

