1 | // Copyright 2014 The Flutter Authors. All rights reserved. |
2 | // Use of this source code is governed by a BSD-style license that can be |
3 | // found in the LICENSE file. |
4 | |
5 | import 'dart:math' as math; |
6 | import 'package:flutter/material.dart'; |
7 | |
8 | /// Flutter code sample for a [ChangeNotifier] with a [ListenableBuilder]. |
9 | |
10 | void main() { |
11 | runApp(const ListenableBuilderExample()); |
12 | } |
13 | |
14 | class ListModel with ChangeNotifier { |
15 | final List<int> _values = <int>[]; |
16 | List<int> get values => _values.toList(); // O(N), makes a new copy each time. |
17 | |
18 | void add(int value) { |
19 | _values.add(value); |
20 | notifyListeners(); |
21 | } |
22 | } |
23 | |
24 | class ListenableBuilderExample extends StatefulWidget { |
25 | const ListenableBuilderExample({super.key}); |
26 | |
27 | @override |
28 | State<ListenableBuilderExample> createState() => _ListenableBuilderExampleState(); |
29 | } |
30 | |
31 | class _ListenableBuilderExampleState extends State<ListenableBuilderExample> { |
32 | final ListModel _listNotifier = ListModel(); |
33 | final math.Random _random = math.Random(0); // fixed seed for reproducibility |
34 | |
35 | @override |
36 | Widget build(BuildContext context) { |
37 | return MaterialApp( |
38 | home: Scaffold( |
39 | appBar: AppBar(title: const Text('ListenableBuilder Example' )), |
40 | body: ListBody(listNotifier: _listNotifier), |
41 | floatingActionButton: FloatingActionButton( |
42 | onPressed: |
43 | () => _listNotifier.add( |
44 | _random.nextInt(1 << 31), |
45 | ), // 1 << 31 is the maximum supported value |
46 | child: const Icon(Icons.add), |
47 | ), |
48 | ), |
49 | ); |
50 | } |
51 | } |
52 | |
53 | class ListBody extends StatelessWidget { |
54 | const ListBody({super.key, required this.listNotifier}); |
55 | |
56 | final ListModel listNotifier; |
57 | |
58 | @override |
59 | Widget build(BuildContext context) { |
60 | return Center( |
61 | child: Column( |
62 | crossAxisAlignment: CrossAxisAlignment.stretch, |
63 | children: <Widget>[ |
64 | const Text('Current values:' ), |
65 | Expanded( |
66 | child: ListenableBuilder( |
67 | listenable: listNotifier, |
68 | builder: (BuildContext context, Widget? child) { |
69 | // We rebuild the ListView each time the list changes, |
70 | // so that the framework knows to update the rendering. |
71 | final List<int> values = listNotifier.values; // copy the list |
72 | return ListView.builder( |
73 | itemBuilder: |
74 | (BuildContext context, int index) => |
75 | ListTile(title: Text(' ${values[index]}' )), |
76 | itemCount: values.length, |
77 | ); |
78 | }, |
79 | ), |
80 | ), |
81 | ], |
82 | ), |
83 | ); |
84 | } |
85 | } |
86 | |