0

Okay. So I'm going to show some code, and I honestly don't know WHY it doesn't work. I just feel like I'm out of my depth, and this is very frustrating.

Now this is NOT the program I'm actually working on, but a super-simple example program that should show the issue I'm having. Please do NOT ask me to put all of these things into or inside a single function or class, as that is NOT an option with my real program, so it wouldn't solve my actual issue.

so in my main.dart I have the following.

import 'package:flutter/cupertino.dart';
import 'dart:async';
import './page2.dart';

void main() => runApp(MyApp());

Page2 myPage = new Page2();
PageState myState = myPage.createState();


class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return CupertinoApp(
      title: 'Splash Test',
      theme: CupertinoThemeData(
        primaryColor: Color.fromARGB(255, 0, 0, 255),
      ),
      home: MyHomePage(title: 'Splash Test Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  bool textBool = false;

  void changeTest(dynamic function, context) async {
    Timer.periodic(Duration (seconds: 2), (Timer t) {
      myState.changeText();
      counter++;
      if (counter >= 10) {
        t.cancel();
      }
    },);
    Navigator.push(context, CupertinoPageRoute(builder: (context) => myPage));


  }



  @override
  Widget build(BuildContext context) {

    return CupertinoPageScaffold(
      child: Center(
        child: CupertinoButton(
          child: Text('To Splash'),
          onPressed: () => changeTest(myState.changeText, context),
        ),
      ), 
    );
  }
}

and in a second Dart file I have

import 'package:flutter/material.dart';
import 'package:flutter/semantics.dart';

import './main.dart';


class Page2 extends StatefulWidget {
  @override 
  State<StatefulWidget> createState() => new PageState();
}

class PageState extends State<Page2> {

bool textChanger = false;
bool firstText = true;

Text myText() {
  if (textChanger) {
    Text text1 = new Text('Text One', 
      style: TextStyle(color: Color.fromARGB(255, 0, 0, 0)));
    return text1;
  } else {
    Text text1 = new Text('Text Two', 
      style: TextStyle(color: Color.fromARGB(255, 0, 0, 0)));
    return text1;
  }
}

void changeText() {
  if (!firstText) {
    if (textChanger) {
      print('Change One');
        textChanger = false;  
      setState(() {     
      });
    } else {
      print('Change Two');
        textChanger = true;  
      setState(() {    
      });
    }  
  } else {
    firstText = false;
  }
}


  @override 
  Widget build(BuildContext context) {
    return new Scaffold(
      body: new Container(
        child: Center(
          child: myText()
        ) 
      ),);
  }
}

Now what this program does is switch to the second page, and then stalls, and nothing happens. The timer IS getting called (I can see this through the print-screen function) And I can see that the text SHOULD be changing, as the bools are being altered properly to do so.

Expected functionality: I should be able to call the instance of the second page, and the functions on it, from my main app, and make changes to the text on that second page.

In my real app (Far more complicated, I couldn't possibly parse it down into something that would fit here) I have the same issue. (If I use the hot reload in Flutter the text DOES change in my actual app.)

So as you can see, I'm trying to communicate cross-classes and cross-functions, but either A) I'm not communicating correctly, or B) The communication is with an incorrect instance of the secondary page, and so the setState() call isn't being done on the variant that's being shown? Those are my only guesses.

ArthurEKing
  • 158
  • 2
  • 16

1 Answers1

2

You shouldn't call the createState manually. For implementing such a thing I prefer to use a stream instead, which is pretty much easy to handle.

timerStream.dart

import 'dart:async';

class TimerStream {
  StreamController _streamController;

  StreamSink<bool> get timerSink =>
      _streamController.sink;

  Stream<bool> get timerStream =>
      _streamController.stream;

  TimerStream() {
    _streamController = StreamController<bool>();
  }

  dispose() {
    _streamController?.close();
  }
}

main.dart

import 'dart:async';
import 'package:flutter/cupertino.dart';
import './page2.dart';
import './timerStream.dart';

void main() => runApp(MyApp());
TimerStream stream = TimerStream();

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return CupertinoApp(
      title: 'Splash Test',
      theme: CupertinoThemeData(
        primaryColor: Color.fromARGB(255, 0, 0, 255),
      ),
      home: MyHomePage(title: 'Splash Test Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  bool textBool = false;

  void changeTest(context) async {

    Navigator.push(context, CupertinoPageRoute(builder: (context) => Page2(stream: stream,)));
    Timer.periodic(Duration (seconds: 5), (Timer t) {
      stream.timerSink.add(true);
    });
  }

  @override
  Widget build(BuildContext context) {

    return CupertinoPageScaffold(
      child: Center(
        child: CupertinoButton(
          child: Text('To Splash'),
          onPressed: () => changeTest(context),
        ),
      ),
    );
  }
}

page2.dart

import 'package:flutter/material.dart';
import 'timerStream.dart';

class Page2 extends StatefulWidget {
  TimerStream stream;
  Page2({this.stream});

  @override
  State<StatefulWidget> createState() => new PageState();
}

class PageState extends State<Page2> {

  bool textChanger = false;
  bool firstText = true;

  Text myText() {
    if (textChanger) {
      Text text1 = new Text('Text One',
          style: TextStyle(color: Color.fromARGB(255, 0, 0, 0)));
      return text1;
    } else {
      Text text1 = new Text('Text Two',
          style: TextStyle(color: Color.fromARGB(255, 0, 0, 0)));
      return text1;
    }
  }

  void changeText() {
    if (!firstText) {
      if (textChanger) {
        print('Change One');
        setState(() {
          textChanger = false;
        });
      } else {
        print('Change Two');
        setState(() {
          textChanger = true;
        });
      }
    } else {
      firstText = false;
    }
  }


  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      body: new Container(
          child: Center(
              child: myText()
          )
      ),);
  }

  @override
  void initState() {
    super.initState();
    widget.stream.timerStream.listen((onData) {
      changeText();
    });
  }
}

Note: If you want, instead of writing true to the stream you can toggle the value and use that in your page2 to change the text.

Midhun MP
  • 103,496
  • 31
  • 153
  • 200
  • I figured I would need to use streams, but I honestly didn't understand (And probably still don't, lol) the syntax of their implementation. At least this gives me an idea of how it SHOULD be... So we'll see if I can correctly implement this in my real project. Thanks! – ArthurEKing Jan 31 '20 at 18:43
  • @ArthurEKing: If you are stuck or have any questions, please don't hesitate to ask. Happy Coding!!! – Midhun MP Feb 01 '20 at 16:33
  • Much appreciated! I had questions, but managed to figure them out. Thanks for pointing me in the right direction! I did manage to complete that in my actual project. Weirdly enough it didn't work until I added the MyHomePage({Key key, this.title}) : super(key: key); line, which I'm not sure what it does... Weird. – ArthurEKing Feb 03 '20 at 14:59
  • @ArthurEKing It's a good article about Flutter Key: https://medium.com/flutter/keys-what-are-they-good-for-13cb51742e7d – Midhun MP Feb 03 '20 at 18:00