界面如上,整个组件为Tabs,状态管理类TabsProvider,里面维护了一个集合items,表示有多少“项”,构建“项”独立成方法_buildTabItem
,我的想法是,点击“增加一项”按钮时,在数组末尾追加一项,为了更好的性能,我想着只会调用一次_buildTabItem
(打印build_tabs_item
),但是目前的效果是,增加一项,集合中所有的“项”都会重新构建。
注:因为我看到的例子,都是修改集合中的一项,能做到只重新构建被修改的项(仅仅)。想着追加一项,也能做到相同的效果;
动态效果如如下:
代码如下:
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'dart:math' as math;
class TabsProvider with ChangeNotifier {
final List<TabItem> _items = [
TabItem(id: 1, title: 'Tab 1'),
TabItem(id: 2, title: 'Tab 2'),
TabItem(id: 3, title: 'Tab 3'),
];
List<TabItem> get items => List.unmodifiable(_items);
appendItem(TabItem item) {
_items.add(item);
notifyListeners();
}
}
// ignore: camel_case_types
class otherDemoIndexRoute extends StatefulWidget {
const otherDemoIndexRoute({super.key});
@override
State<otherDemoIndexRoute> createState() => _otherDemoIndexRouteState();
}
// ignore: camel_case_types
class _otherDemoIndexRouteState extends State<otherDemoIndexRoute> {
@override
Widget build(BuildContext context) {
print('主入口');
return Scaffold(
appBar: AppBar(title: Text('自定义控制器示例')),
body: ChangeNotifierProvider(
create: (context) => TabsProvider(),
child: SingleChildScrollView(
padding: const EdgeInsets.all(16.0),
child: Tabs(),
),
),
);
}
}
class Tabs extends StatefulWidget {
const Tabs({super.key});
@override
State<Tabs> createState() => _TabsState();
}
class _TabsState extends State<Tabs> {
@override
Widget build(BuildContext context) {
return Column(
children: [
Selector<TabsProvider, List<TabItem>>(
selector: (context, provider) => provider.items,
shouldRebuild: (previous, next) {
return previous.length != next.length;
},
builder: (context, tabList, child) {
print('构建整个Tabs组件');
List<Widget> widgets = [];
for (var item in tabList) {
widgets.add(_buildTabItem(context, item));
}
return Wrap(spacing: 10, children: [...widgets]);
},
),
Wrap(
spacing: 10,
children: [
TextButton(
onPressed: () {
var tabsProvider = context.read<TabsProvider>();
var list = tabsProvider.items.map((item) => item.id).toList();
int maxValue = list.reduce(
(value, element) => math.max(value, element),
);
tabsProvider.appendItem(
TabItem(id: maxValue + 1, title: 'title${maxValue + 1}'),
);
},
child: Text('增加一项'),
),
],
),
],
);
}
/// 构建TabItem组件
Widget _buildTabItem(BuildContext context, TabItem item) {
print('build_tabs_item');
return Material(
borderRadius: BorderRadius.all(Radius.circular(8.0)),
child: InkWell(
mouseCursor: SystemMouseCursors.click, //forbidden 禁止点击效果
child: Container(
padding: const EdgeInsets.all(8.0),
decoration: BoxDecoration(
border: Border.all(color: Colors.blue),
borderRadius: BorderRadius.circular(8.0),
),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
Text(item.title, style: const TextStyle(color: Colors.black)),
],
),
),
),
);
}
}
class TabItem {
int id;
String title;
TabItem({required this.id, required this.title});
}
建“项”独立成方法_buildTabItem,我的想法是,点击“增加一项”按钮时,在数组末尾追加一项,为了更好的性能,我想着只会调用一次