在研究过程中,我发现了以下内容:
// ignore_for_file: camel_case_types
// ignore_for_file: constant_identifier_names
// ignore_for_file: non_constant_identifier_names
import 'dart:async';
import 'dart:io';
import 'dart:math';
main() {
randomize_flash_indices();
print ( "flash indices : $flash_indices" );
listen_countup();
}
List<int> flash_indices = [ ];
int level = 9;
var random = new Random ( );
void randomize_flash_indices() {
flash_indices.clear();
for ( int i = 0; ( i < level); i++ ) {
flash_indices.add ( random.nextInt ( level ) );
}
} // randomize_flash_indices()
listen_countup() async {
await for (int i in level_countup()) {
int flash_index = flash_indices[i];
print("Flash Tile: $flash_index");
}
} // listen_countup()
Stream<int> level_countup() async* {
for ( int i = 0; ( i < level ); i++ ){
sleep(new Duration(seconds: 1));
yield i;
}
} // level_countup()
执行时,我获得:
I/flutter (27111): flash indices : [5, 3, 7, 7, 7, 4, 3, 1, 0]
I/flutter (27111): Flash Tile: 5
I/flutter (27111): Flash Tile: 3
I/flutter (27111): Flash Tile: 7
I/flutter (27111): Flash Tile: 7
I/flutter (27111): Flash Tile: 7
I/flutter (27111): Flash Tile: 4
I/flutter (27111): Flash Tile: 3
I/flutter (27111): Flash Tile: 1
I/flutter (27111): Flash Tile: 0
每行以大约1秒的间隔输出。这种范例似乎是我实现应用程序屏幕的定期重新渲染所需要的。我的实现是:
// ignore_for_file: camel_case_types
// ignore_for_file: constant_identifier_names
// ignore_for_file: non_constant_identifier_names
// https://stackoverflow.com/questions/52523548/
// rendering-a-screen-on-icon-tap/52525090#52525090
// https://sergiandreplace.com/flutter-animations-the-basics/
import 'package:flutter/material.dart';
import 'dart:async';
import 'dart:io';
import 'appconstants.dart';
import 'appstate.dart';
class Circles extends StatefulWidget {
final AppState app_state;
Circles({
@required this.app_state,
Key key,
}) : super(key: key);
@override
CirclesState createState() =>
new CirclesState();
} // class Circles
class CirclesState extends State<Circles>{
int flash_tile = -1;
List<GridTile> grid_tiles = <GridTile>[];
@override
void initState() {
super.initState();
listen_for_tick();
} // initState()
listen_for_tick() async {
await for (int tick in up_tick()) {
print('listen_for_tick() tick: $tick');
this.setState(() {
this.flash_tile = widget.app_state.flash_indices[tick];
});
}
}// listen_for_tick
Stream<int> up_tick() async* {
for ( int tick = 0; ( tick < widget.app_state.counter ); tick++ ){
print('up_tick() tick: $tick');
sleep(Constants.ONE_SECOND);
yield tick;
}
} // up_tick
GridTile new_circle_tile(Color tile_color,
int index) {
GridTile tile = GridTile(
child: GestureDetector(
child: Container(
decoration: BoxDecoration(
color: tile_color,
shape: BoxShape.circle,
),
),
)
);
return (tile);
} // new_circle_tile
List<GridTile> create_circle_tiles() {
grid_tiles = new List<GridTile>();
for (int i = 0; (i < Constants.NUMBER_TILES); i++) {
Color tile_color = ( this.flash_tile == i) ?
Circle_Colors.bright_colors[i] :
Circle_Colors.normal_colors[i];
grid_tiles.add(new_circle_tile(tile_color, i));
}
return (grid_tiles);
} // create_circle_tiles
@override
Widget build(BuildContext context) {
print(widget.app_state.toString()+' flash_tile: $flash_tile');
return GridView.count(
shrinkWrap: true,
crossAxisCount: Constants.CROSS_AXIS_COUNT,
childAspectRatio: 1.0,
padding: const EdgeInsets.all(4.0),
mainAxisSpacing: Constants.MAIN_AXIS_SPACING,
crossAxisSpacing: Constants.CROSS_AXIS_SPACING,
children: create_circle_tiles(),
);
}
} // class CirclesState
我每次点击AppBar图标时都会发生的事情是,每个圆圈都会按照flash_indices中指定的顺序闪烁。相反,我得到的是屏幕显示没有变化,而是:
Launching lib\main.dart on SM G925V in debug mode...
Built build\app\outputs\apk\debug\app-debug.apk.
I/flutter (28374): AppState{counter: 0, flash_indices: []} flash_tile: -1
D/ViewRootImpl@6af19[MainActivity](28374): ViewPostImeInputStage processPointer 0
W/System (28374): ClassLoader referenced unknown path: /system/framework/QPerformance.jar
E/BoostFramework(28374): BoostFramework() : Exception_1 = java.lang.ClassNotFoundException: Didn't find class "com.qualcomm.qti.Performance" on path: DexPathList[[],nativeLibraryDirectories=[/system/lib64, /vendor/lib64]]
V/BoostFramework(28374): BoostFramework() : mPerf = null
D/ViewRootImpl@6af19[MainActivity](28374): ViewPostImeInputStage processPointer 1
D/ViewRootImpl@6af19[MainActivity](28374): ViewPostImeInputStage processPointer 0
D/ViewRootImpl@6af19[MainActivity](28374): ViewPostImeInputStage processPointer 1
I/flutter (28374): AppState{counter: 1, flash_indices: [0]} flash_tile: -1
D/ViewRootImpl@6af19[MainActivity](28374): ViewPostImeInputStage processPointer 0
D/ViewRootImpl@6af19[MainActivity](28374): ViewPostImeInputStage processPointer 1
I/flutter (28374): AppState{counter: 2, flash_indices: [1, 1]} flash_tile: -1
D/ViewRootImpl@6af19[MainActivity](28374): ViewPostImeInputStage processPointer 0
D/ViewRootImpl@6af19[MainActivity](28374): ViewPostImeInputStage processPointer 1
I/flutter (28374): AppState{counter: 3, flash_indices: [0, 0, 0]} flash_tile: -1
D/ViewRootImpl@6af19[MainActivity](28374): ViewPostImeInputStage processPointer 0
D/ViewRootImpl@6af19[MainActivity](28374): ViewPostImeInputStage processPointer 1
I/flutter (28374): AppState{counter: 4, flash_indices: [0, 2, 2, 2]} flash_tile: -1
Application finished.
Exited (sigterm)
似乎没有调用过listen_for_tick()。我不知道怎么了。
答案 0 :(得分:0)
我认为sleep
是您的恶棍,它是同步的,将其放在for
中会干扰应用程序重新绘制自身的方式。 sleep
锁定线程,应用程序挂在那里,而不是被重新绘制。
我已使用StreamController
和StreamSubscription
重写了您的代码。我使用了sleep
,而不是Future.delay
。查看是否可以调整代码以使用控制器和订阅。
import 'package:flutter/material.dart';
import 'dart:async';
import 'dart:io';
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'Periodic',
theme: new ThemeData(primarySwatch: Colors.indigo),
home: new Circles(),
);
}
}
class AppState {
AppState() {
flash_indices = [5, 0, 3, 6, 2, 1, 4];
counter = flash_indices.length;
}
List<int> flash_indices;
int counter;
String toString() {
return "FakeAppState";
}
StreamController<int> _tickController;
Stream<int> startTicking() {
_tickController = new StreamController();
for ( int tick = 0; ( tick < counter ); tick++ ) {
Future.delayed(Duration(seconds: tick), () {
print('startTicking() tick: $tick');
_tickController.add(tick);
});
}
return _tickController.stream;
}
}
class Circles extends StatefulWidget {
final app_state = new AppState();
@override
CirclesState createState() => new CirclesState();
}
class CirclesState extends State<Circles>{
int flash_tile = -1;
List<GridTile> grid_tiles = <GridTile>[];
StreamSubscription<int> tickListener;
@override
void initState() {
super.initState();
tickListener = widget.app_state.startTicking().listen(_individualTickListener);
}
@override
void dispose() {
if (tickListener != null) {
tickListener.cancel();
tickListener = null;
}
super.dispose();
}
_individualTickListener(int tick) async {
print('listen_for_tick() tick: $tick');
this.setState(() => this.flash_tile = widget.app_state.flash_indices[tick]);
}
GridTile new_circle_tile(Color tile_color,
int index) {
GridTile tile = GridTile(
child: GestureDetector(
child: Container(
decoration: BoxDecoration(
color: tile_color,
shape: BoxShape.circle,
),
),
)
);
return (tile);
}
List<GridTile> create_circle_tiles() {
grid_tiles = new List<GridTile>();
for (int i = 0; (i < widget.app_state.counter); i++) {
Color tile_color = ( this.flash_tile == i) ?
Colors.yellow : Colors.green;
grid_tiles.add(new_circle_tile(tile_color, i));
}
return (grid_tiles);
}
@override
Widget build(BuildContext context) {
print(widget.app_state.toString()+' flash_tile: $flash_tile');
return Column(
children: [
GridView.count(
shrinkWrap: true,
crossAxisCount: widget.app_state.counter,
childAspectRatio: 1.0,
padding: const EdgeInsets.all(4.0),
mainAxisSpacing: 2.0,
crossAxisSpacing: 2.0,
children: create_circle_tiles(),
),
RaisedButton(
child: Text("restart"),
onPressed: () {
tickListener = widget.app_state.startTicking().listen(_individualTickListener);
}
),
]
);
}
}