性能优化demo
2023-07-18 本文已影响0人
Crassus
Future<String> fetchData2(String input) async {
await Future.delayed(const Duration(seconds: 5));
return 'Hello, $input!';
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key, required this.title});
final String title;
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int index = 0;
StreamController<int> _counterController = StreamController<int>();
int _counter = 0;
void _incrementCounter() {
if (index == 0) {
index = 1;
} else {
index = 0;
}
_counter++;
_counterController.sink.add(_counter);
setState(() {});
}
@override
void dispose() {
_counterController.close();
super.dispose();
}
Future<String> fetchData() async {
return Future.delayed(const Duration(seconds: 3), () => 'Hello, world!');
}
Future<List<String>> fetchData3() async {
List<Future<String>> futures = [
Future.delayed(const Duration(seconds: 1), () => 'Hello'),
Future.delayed(const Duration(seconds: 2), () => 'World!!!'),
];
List<String> results = await Future.wait(futures);
return results;
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
title: Text(widget.title),
),
body: Center(
child: Column(
children: [
IndexedStackWidget(
index: index,
),
// 异步
FutureBuilder(
future: fetchData(),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
return Text(snapshot.data ?? '');
} else {
return const CircularProgressIndicator();
}
},
),
// isolate获取数据
FutureBuilder(
future: compute(fetchData2, 'world'),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
return Text(snapshot.data ?? '');
} else {
return const CircularProgressIndicator();
}
},
),
// stream 流显示
StreamBuilder<int>(
stream: _counterController.stream,
builder: (context, snapshot) {
if (snapshot.hasData) {
return Text('Counter: ${snapshot.data}');
} else {
return const CircularProgressIndicator();
}
},
),
/// 多异步操作
FutureBuilder(
future: fetchData3(),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
if (snapshot.hasData) {
return Text(snapshot.data?.join(' ') ?? '');
} else if (snapshot.hasError) {
return Text('Error: ${snapshot.error}');
} else {
return const Text('No data');
}
} else {
return const CircularProgressIndicator();
}
},
)
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: const Icon(Icons.add),
),
);
}
}
class FlexDemo extends StatelessWidget {
const FlexDemo({super.key});
@override
Widget build(BuildContext context) {
return Flex(
direction: Axis.horizontal,
children: [
Expanded(
child: Container(
height: 100,
color: Colors.red,
),
),
Expanded(
child: Container(
height: 100,
color: Colors.blue,
),
),
],
);
}
}
class MyLayoutDelegate extends MultiChildLayoutDelegate {
MyLayoutDelegate({this.position});
final Offset? position;
@override
void performLayout(Size size) {
// `size` is the size of the `CustomMultiChildLayout` itself.
Size leadingSize = Size
.zero; // If there is no widget with id `1`, the size will remain at zero.
// Remember that `1` here can be any **id** - you specify them using LayoutId.
if (hasChild(1)) {
leadingSize = layoutChild(
1, // The id once again.
BoxConstraints.tightFor(
height: size
.height), // This just says that the child cannot be bigger than the whole layout.
);
// No need to position this child if we want to have it at Offset(0, 0).
}
if (hasChild(2)) {
final secondSize = layoutChild(
2,
BoxConstraints.tightFor(width: size.width / 2),
);
positionChild(
2,
Offset(
leadingSize.width, // This will place child 2 to the right of child 1.
size.height / 2 -
secondSize.height / 2, // Centers the second child vertically.
),
);
}
}
@override
bool shouldRelayout(MyLayoutDelegate oldDelegate) =>
oldDelegate.position != position;
}
class MultiChild extends StatelessWidget {
const MultiChild({super.key});
@override
Widget build(BuildContext context) {
return CustomMultiChildLayout(
delegate: MyLayoutDelegate(),
children: [
LayoutId(
id: 1, // The id can be anything, i.e. any Object, also an enum value.
child: const Text(
'Widget one'), // This is the widget you actually want to show.
),
LayoutId(
id: 2, // You will need to refer to that id when laying out your children.
child: const Card(
child: Padding(
padding: EdgeInsets.all(8.0),
child: Text('Widget two'),
),
),
),
],
);
}
}
class IndexedStackWidget extends StatelessWidget {
final int index;
const IndexedStackWidget({super.key, required this.index});
@override
Widget build(BuildContext context) {
return IndexedStack(
index: index,
children: [
Container(
width: 100,
height: 100,
color: Colors.red,
),
Container(
width: 100,
height: 100,
color: Colors.blue,
),
],
);
}
}