面试题答案
一键面试1. 设计状态结构
- 原则:将状态按照是否会频繁变动进行拆分。对于不常变动的状态与频繁变动的状态分开管理,避免因频繁变动的状态更新而导致不相关部分重绘。
- 示例:假设我们有一个简单的电商应用,有商品列表和购物车功能。商品列表数据不常变动,而购物车中的商品数量会频繁变动。
class Product {
final String name;
final double price;
Product(this.name, this.price);
}
class CartItem {
final Product product;
int quantity;
CartItem(this.product, this.quantity);
}
class AppState {
List<Product> products;
List<CartItem> cartItems;
AppState({required this.products, required this.cartItems});
}
2. 使用细粒度的ChangeNotifier
- 原则:针对每个可能单独变动的状态部分,创建一个细粒度的
ChangeNotifier
。这样,只有该部分状态变化时,与之关联的组件才会重绘。 - 示例:对于购物车数量变动,我们创建一个单独的
CartNotifier
。
import 'package:flutter/foundation.dart';
class CartNotifier extends ChangeNotifier {
List<CartItem> cartItems = [];
void addToCart(Product product) {
final existingItem = cartItems.firstWhere((item) => item.product == product, orElse: () => null);
if (existingItem != null) {
existingItem.quantity++;
} else {
cartItems.add(CartItem(product, 1));
}
notifyListeners();
}
void removeFromCart(Product product) {
final existingItem = cartItems.firstWhere((item) => item.product == product, orElse: () => null);
if (existingItem != null) {
if (existingItem.quantity > 1) {
existingItem.quantity--;
} else {
cartItems.remove(existingItem);
}
notifyListeners();
}
}
}
3. 选择性监听
- 原则:在使用
Consumer
时,通过builder
的child
参数和Consumer
的listen
属性,只监听需要的状态变化。 - 示例:在商品列表展示时,只关注商品列表数据,不关心购物车状态。
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
class ProductListScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Product List')),
body: Consumer<AppState>(
builder: (context, appState, child) {
return ListView.builder(
itemCount: appState.products.length,
itemBuilder: (context, index) {
final product = appState.products[index];
return ListTile(
title: Text(product.name),
subtitle: Text('Price: ${product.price}'),
);
},
);
},
listen: false, // 不监听状态变化,因为商品列表数据不变动
),
);
}
}
class CartScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Cart')),
body: Consumer<CartNotifier>(
builder: (context, cartNotifier, child) {
return ListView.builder(
itemCount: cartNotifier.cartItems.length,
itemBuilder: (context, index) {
final cartItem = cartNotifier.cartItems[index];
return ListTile(
title: Text(cartItem.product.name),
subtitle: Text('Quantity: ${cartItem.quantity}'),
trailing: IconButton(
icon: Icon(Icons.remove),
onPressed: () => cartNotifier.removeFromCart(cartItem.product),
),
);
},
);
},
),
);
}
}
通过以上设计状态结构和更新逻辑的方式,在使用Provider进行状态管理时,可以有效避免不必要的重绘,提高应用性能。