Метод рисования CustomPainter не вызывается перед WidgetsBinding.instance.addPostFrameCallback в случае множественной навигации

У меня есть Flutter StatefulWidget, и в методе initState() я использую WidgetsBinding.instance.addPostFrameCallback для использования одной переменной экземпляра (поздний список _tracks). нравиться -

      WidgetsBinding.instance.addPostFrameCallback((_) {
      for(itr = 0; itr<_tracks.length; itr++){
         // some logic
      }
    });

Поскольку это будет вызвано после того, как все виджеты будут выполнены. В одном из классов рисования CustomPaint я инициализирую эту переменную.

      SizedBox.expand(
       child: CustomPaint(
            painter: TrackPainter(
                   trackCalculationListener: (tracks) {
                     _tracks = tracks;
              }),
           ),
        ),

Он отлично работает, когда у меня есть один экран, т.е. тот же класс. Но когда я добавляю один экран перед этим и пытаюсь перейти к этому экрану с нового экрана, он выдает исключение _tracks is not initialized. новый экран очень простой -

      class MainMenu extends StatefulWidget {
  const MainMenu({super.key});

  @override
  State<MainMenu> createState() => _MainMenuState();
}

class _MainMenuState extends State<MainMenu> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Container(
        color: Colors.white,
        child: ElevatedButton(
          onPressed: () {
            Navigator.push(
                context,
                MaterialPageRoute(
                    builder: (context) => const Play(),
                    maintainState: false));
          },
          child: const Text('play game'),
        ),
      ),
    );
  }
}

В случае одного экрана метод рисования рисовальщика вызывается до postFrameCallback, но в случае нескольких он не вызывается перед postFrameCallback, и из-за этого переменная не инициализируется.

воспроизводимый код -

      import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      routes: {
        '/mainMenu': (context) => const MainMenu(),
        '/game': (context) => const MyHomePage(title: 'game'),
      },
      initialRoute: '/mainMenu',
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key, required this.title});

  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  late List<Rect> _playerTracks;

  @override
  void initState() {
    super.initState();

    WidgetsBinding.instance.addPostFrameCallback((_) {
      print(_playerTracks.length);
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisSize: MainAxisSize.min,
          children: <Widget>[
            Container(
              color: Colors.white,
              margin: const EdgeInsets.all(20),
              child: AspectRatio(
                aspectRatio: 1,
                child: SizedBox.expand(
                  child: CustomPaint(
                    painter: RectanglePainter(
                        trackCalculationListener: (playerTracks) =>
                            _playerTracks = playerTracks),
                  ),
                ),
              ),
            )
          ],
        ),
      ),
    );
  }
}

class MainMenu extends StatefulWidget {
  static String route = '/mainMenu';
  const MainMenu({super.key});

  @override
  State<MainMenu> createState() => _MainMenuState();
}

class _MainMenuState extends State<MainMenu> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Container(
          height: 200.0,
          color: Colors.white,
          child: ElevatedButton(
            onPressed: () {
              Navigator.pushNamed(context, '/game');
            },
            child: const Text('play game'),
          ),
        ),
      ),
    );
  }
}

class RectanglePainter extends CustomPainter {
  Function(List<Rect>) trackCalculationListener;

  RectanglePainter({required this.trackCalculationListener});

  @override
  void paint(Canvas canvas, Size size) {
    final Rect rect = Offset.zero & size;
    const RadialGradient gradient = RadialGradient(
      center: Alignment(0.7, -0.6),
      radius: 0.2,
      colors: <Color>[Color(0xFFFFFF00), Color(0xFF0099FF)],
      stops: <double>[0.4, 1.0],
    );
    canvas.drawRect(
      rect,
      Paint()..shader = gradient.createShader(rect),
    );
    List<Rect> _playerTracks = [];
    _playerTracks.add(rect);
    trackCalculationListener(_playerTracks);
  }

  @override
  bool shouldRepaint(CustomPainter oldDelegate) => true;
}

Я очень новичок в флаттере и был бы очень признателен, если бы кто-нибудь помог мне понять, что я здесь делаю неправильно.

0 ответов

Другие вопросы по тегам