颤振状态管理示例 [英] Flutter State Management Examples

查看:80
本文介绍了颤振状态管理示例的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在复杂的应用程序中,有时可以通过某些外部事件"更改附加"到小部件的全局变量,例如(1)在另一个线程中运行的计时器,或(2)socket.io服务器发出事件(3)其他...

In a complex app, sometimes a Global Variable 'attached' to a widget, can be changed by some 'EXTERNAL EVENT' such as (1) A timer that run in another thread, or (2) socket.io server emit event (3) Others ......

我们将此全局变量称为gintCount,该应用程序有3个页面,即:

Let's call this global variable gintCount and the app has 3 pages, namely:

  1. 页面1:动态"页面,需要显示gintCount的最新值.
  2. 第2页:另一个动态"页面,需要显示gintCount的最新值以及文本输入字段.
  3. 第3页:当gintCount更改时,不执行任何操作的静态"页面.

假设用户正在执行第1页或第2页中的操作,我们何时何地应该刷新"页面以显示EXTERNAL事件可能/可能更改的最新值?

Suppose the user is doing something in Page 1 or Page 2, when and where should we 'Refresh' the page to display the latest value that may/might be changed by EXTERNAL event?

我阅读了《堆栈溢出》中的其他问答,据说Flutter的状态管理有4种方法,分别是:

I read the other Q&A in Stack Overflow and it is said that there are 4 ways for the State Management of Flutter, they are namely:

  1. 使用setState
  2. 使用ScopedModal
  3. 将Rxdart与BLoC一起使用
  4. 使用Redux

由于我是Flutter的新手,所以我在2到4中完全迷失了,因此我使用no构建了一个应用程序. 1,即setState.演示如何管理抖动中的状态.我希望将来,我能够(或其他人)通过使用no来提供答案. 2至4.

Since I'm a newbie in Flutter, I am completely lost in 2 to 4, so I've build an app using no. 1, i.e. setState. to demonstrate how we can manage states in flutter. And I hope, in the future, I am able to (or somebody else) provide answers by using no. 2 to 4.

下面的动画gif中让我们看一下正在运行的应用程序:

Let's take a look at the running app in the following animation gif:

屏幕快照Gif链接

如gif所示,在第1页和第2页中都有一个全局计数器,而第3页是静态页.

As you can see in the gif, there is a Global Counter in Page 1 and Page 2, and Page 3 is a static Page.

让我解释一下我是怎么做到的:

Let me explain how I did it:

完整的源代码可以在以下地址找到:

The complete source code can be found at the following address:

https://github.com/lhcdims/statemanagement01

有7个飞镖文件,它们是:

There are 7 dart files, they are namely:

  1. gv.dart:存储所有全局变量.
  2. ScreenVariable.dart:获取屏幕等的高度/宽度/字体大小.您可以忽略它.
  3. BottomBar.dart:底部导航栏.
  4. main.dart:主程序.
  5. Page1.dart:第1页小部件.
  6. Page2.dart:第2页小部件.
  7. Page3.dart:第3页小部件.

让我们首先看一下gv.dart:

Let's first take a look at gv.dart:

import 'package:flutter/material.dart';
class gv {
  static var gstrCurPage = 'page1'; // gstrCurPage stores the Current Page to be loaded

  static var gintBottomIndex = 0; // Which Tab is selected in the Bottom Navigator Bar

  static var gintCount = 0; // The Global Counter
  static var gintCountLast = 0; // Check whether Global Counter has been changed

  static var gintPage1Counter = 0; // No. of initState called in Page 1
  static var gintPage2Counter = 0; // No. of initState called in Page 2
  static var gintPage3Counter = 0; // No. of initState called in Page 3

  static bool gbolNavigatorBeingPushed = false; // Since Navigator.push will called the initState TWICE, this variable make sure the initState only be called once effectively!

  static var gctlPage2Text = TextEditingController(); // Controller for the text field in Page 2
}

我如何模拟更改全局变量gv.gintCount的外部事件?

How did I simulate an External Event that changes the global variable gv.gintCount?

好吧,我在main.dart中创建了一个运行计时器'funTimerExternal'的线程,并每秒增加gv.gintCount!

Ok, I create a thread in main.dart that runs the timer 'funTimerExternal', and increment gv.gintCount every second!

现在,让我们看一下main.dart:

Now, let's take a look at main.dart:

    // This example tries to demonstrate how to maintain the state of widgets when
    // variables are changed by External Event
    // e.g. by a timer of another thread, or by socket.io
    // This example uses setState and a timer to maintain States of Multiple Pages

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import "package:threading/threading.dart";

import 'gv.dart';
import 'Page1.dart';
import 'Page2.dart';
import 'Page3.dart';
import 'ScreenVariables.dart';


void main() {  // Main Program
  var threadExternal = new Thread(funTimerExternal);    // Create a new thread to simulate an External Event that changes a global variable defined in gv.dart
  threadExternal.start();

  SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp])
      .then((_) {
      sv.Init();        // Init Screen Variables

      runApp(new MyApp());        // Run MainApp
  });
}


void funTimerExternal() async {  // The following function simulates an External Event  e.g. a global variable is changed by socket.io and see how all widgets react with this global variable
  while (true) {
    await Thread.sleep(1000);
    gv.gintCount += 1;
  }
}



class MyApp extends StatefulWidget {  // Main App
  @override
  _MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
  @override
  initState() {
    super.initState();
    var threadTimerDefault = new Thread(funTimerDefault);      // *** Set funTimerDefault, to listen to change of Vars ***
    threadTimerDefault.start();
  }

  void funTimerDefault() async {
    while (true) {
      await Thread.sleep(500);        // Allow this thread to run each XXX milliseconds

      if (gv.gintCount != gv.gintCountLast) {        // Check any changes need to setState here, if anything changes, setState according to gv.gstrCurPage
        gv.gintCountLast = gv.gintCount;
        switch (gv.gstrCurPage) {
          case 'page1':
            setState(() {});              // Page 1: Refresh Page
            break;
          case 'page2':
            setState(() {});              // Page 2: Refresh Page
            break;
          default:              // Page 3: Do Nothing, since Page 3 is static
            break;
        }
      }
    }
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,        // Disable Show Debug

      home: MainBody(),
    );
  }
}
class MainBody extends StatefulWidget {
  @override
  _MainBodyState createState() => _MainBodyState();
}
class _MainBodyState extends State<MainBody> {
  @override
  initState() {
    super.initState();
  }
  @override
  Widget build(BuildContext context) {
    switch (gv.gstrCurPage) {      // Here Return Page According to gv.gstrCurPage
      case 'page1':
        return ClsPage1();
        break;
      case 'page2':
        return ClsPage2();
        break;
      default:
        return ClsPage3();
        break;
    }
    return ClsPage1();      // The following code will never be run, to avoid warning only
  }
}

如您所见,我使用另一个计时器'funTimerDefault'来跟踪gv.gintCount中的更改,并确定是否应每XXX毫秒调用一次setState. (XXX当前设置为500)

As you can see, I use another timer 'funTimerDefault' to keep track of changes in gv.gintCount, and determine whether setState should be called every XXX milliseconds. (XXX is currently set at 500)

我知道,这很愚蠢!

如何通过将ScopedModal或Rxdart与BLoC或Redux一起使用来创建类似的示例?

How can I create similar examples by using ScopedModal, or Rxdart with BLoC, or Redux?

在任何人提供任何答案之前,请记住,全局变量gintCount不会由任何用户交互更改,而是由不属于任何小部件的外部事件更改.例如,您可以将此应用视为:

Before anyone provides any answers, please bear in mind that the Global Variable gintCount, is not changed by ANY USER INTERACTION, but an EXTERNAL EVENT that IS NOT PART OF ANY WIDGETS. For example, you can regard this app as:

  1. 一个CHAT应用程序,"gintCount"是其他人通过socket.io服务器发送给您的消息.或者,

  1. A CHAT app, that 'gintCount' is a message sent to you by someone else thru socket.io server. Or,

一个多人在线游戏,"gintCount"是您屏幕中另一位玩家的位置,该位置由该玩家使用另一部手机控制!

A Multi-Player On-line Game, that 'gintCount' is the position of another player in YOUR SCREEN, which is controlled by that player using another Mobile Phone!

推荐答案

对于您的需求,您绝对应该更多地研究您所讨论的可用体系结构. 例如,REDUX完全符合解决问题所需的条件.

For your need, you should definitely look more into the architectures available, that you talked about. For example, REDUX matches exactly what you need to solve your issue.

我只能建议您看一下REDUX的此演示文稿: https://www.youtube.com/watch?v=zKXz3pUkw9A

I can only advise you to take a look at this presentation of REDUX : https://www.youtube.com/watch?v=zKXz3pUkw9A

即使对于这种模式的新手来说,这也是非常容易理解的(这是我不久前才想到的). 完成此操作后,请查看 http://fluttersamples.com/

It is very understandable even for newbies of this pattern (which I was not so long ago). When you've done that, take a look at http://fluttersamples.com/

该网站包含许多不同模式的示例项目.这可以帮助您入门

This website contains example projects for a dozen of different patterns. That may help you get started

这篇关于颤振状态管理示例的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆