Обновление виджета и проблема с setStat

avatar
user5824983
1 июля 2021 в 17:04
50
1
0

В настоящее время я работаю над этим руководством, в котором переменная "myVariable" передается из внешнего файла в другой. Связь: https://dev.to/lucianojung/global-variable-access-in-flutter-3ijm

Я изменил свой код, чтобы переменную "myVariable" можно было использовать в файле myservice.dart, это работает, но проблема в том, что я не могу динамически обновлять свой текстовый виджет "widget.myVariable", он обновляется только тогда, когда я это делаю «горячая перезагрузка». Я думаю, что мы должны добавить setStat, но я не знаю, как это реализовать, несмотря на несколько попыток.

Спасибо за помощь

myservice.dart

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

class MyService extends StatefulWidget {
  //Passed 'myVariable' ///////////////////////////////////////////////////
  static final MyService _instance = MyService._internal();
  // passes the instantiation to the _instance object
  factory MyService() => _instance;
  //initialize variables in here
  MyService._internal() {
    _myVariable = 0;
  }
  int _myVariable;
  //short getter for my variable
  int get myVariable => _myVariable;
  //short setter for my variable
  set myVariable(int value) => myVariable = value;
  void incrementMyVariable() => _myVariable++;
  /////////////////////////////////////////////////////
  @override
  _MyServiceState createState() => _MyServiceState();
}

class _MyServiceState extends State<MyService> {

  /* i try this but no result
   _displayCounter() {
     setState(() {
       widget.myVariable;
     });
   }
*/
  @override
  Widget build(BuildContext context) {
    return Container(
      color: Colors.red,
      width: 250,
      height: 90,
      child: Text(
        // '${_displayCounter()}',
        '${widget.myVariable}',
      ),
    );
  }
}

main.dart

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

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: 'Flutter Service Demo App'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);
  final String title;
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  MyService _myService = MyService();
  _incrementCounter() {
    setState(() {
      _myService.incrementMyVariable();
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              'You have pushed the button this many times:',
            ),
            MyService(), //myservice.dart
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: Icon(Icons.add),
      ),
    );
  }
}
Источник
Sarvesh Dalvi
1 июля 2021 в 18:01
0

Виджет MyService, который вы используете для инициализации вашей переменной здесь: MyService _myService = MyService(); и тот, который вы используете в своем дереве виджетов, оба являются разными объектами. Всякий раз, когда вы вызываете конструктор, например: MyService(), он создает совершенно новый объект со своими свойствами. Попробуйте повторно использовать ту же переменную _myService, которую вы инициализировали в дереве виджетов, чтобы вы использовали тот же объект в дереве виджетов, для которого вы написали функцию setState.

Ответы (1)

avatar
abdev
1 июля 2021 в 20:52
0

Мы используем синглтон, когда нам нужно управлять общим ресурсом. Вы можете прочитать больше здесь.

Здесь вы пытаетесь использовать одноэлементный класс в качестве "виджета".

Очевидно, что вы пытаетесь использовать myVariable. Возможно, вы сможете сделать отдельный виджет, соответствующий этому требованию.

1 -> Изменить main.dart: я буду использовать объект _myService и передать его Service(), где он должен показывать количество.

children: <Widget>[ 
  Text( 
   'You have pushed the button this many times:',
  ),

 /* Now because of setState(), the build method will be called
    as many times as the counter increases, which will call
    Service() with the MyService instance below
  */ 

Service(_myService), //  ------ service_widget.dart 
]

2 -> Оставить myservice.dart как есть (как указано в руководстве).

3 -> service_widget.dart будет выглядеть следующим образом:

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

class Service extends StatelessWidget {

final MyService myService; 
Service(this.myService); // making use of MyService instance

@override
Widget build(BuildContext context) {
  return Container(
    color: Colors.yellow,
    width: double.infinity,
    child: Text(
      '${myService.myVariable}', // Access myVariable here
       textAlign: TextAlign.center,
       style: TextStyle(
         fontSize: 25,
         fontWeight: FontWeight.bold,
        ),
      ),
    );
  }
}  

Flutter App - Counter of Clicks

Теперь все работает нормально!

Хотя вы можете увидеть полный код здесь, я настоятельно рекомендую вам еще немного поиграться.

  1. main.dart

  2. myservice.dart

  3. service_widget.dart

user5824983
2 июля 2021 в 08:41
0

Большое спасибо за вашу работу, код работает нормально, и ваше объяснение понятно, но у меня есть вопрос, как лучше? соберите service_widget.dart и myservice.dart в один файл или сделайте как вы.

abdev
2 июля 2021 в 08:46
1

@igachi myservice.dart здесь, чтобы предоставить вам этот единственный экземпляр и ничего более. Так что, по моему мнению, этот класс и service_widget.dart должны оставаться отдельными. Хотя я также приветствую комментарии от опытных разработчиков.