【问题标题】:Flutter - Provider not updating state stuck in Loading ScreenFlutter - 提供程序未更新卡在加载屏幕中的状态
【发布时间】:2020-06-05 13:45:33
【问题描述】:

我需要专家意见。 我是 Flutter 新手,我似乎无法解决这个问题。

这是我的问题:

我正在构建一个将连接到 MQTT 的应用程序。 订阅一个主题。说话题A。 之后,它会发布一些要说的话题 B。 然后它会收到主题 A 中的一些指令。

所以当它初始化 MQTT 并完成连接过程时,我想显示加载屏幕。 当它完成连接时,我想只显示一个文本的主屏幕。

这是我的提供者处理程序;

import 'package:dnb/screens/loading_screen.dart';
import 'package:dnb/screens/main_screen.dart';
import 'package:flutter/material.dart';
enum MQTTAppConnectionState { connected, disconnected, connecting }
class MQTTAppState with ChangeNotifier {
  MQTTAppConnectionState _appConnectionState =
      MQTTAppConnectionState.disconnected;
  void setAppConnectionState(MQTTAppConnectionState state) {
    _appConnectionState = state;
    notifyListeners();
  }
  MQTTAppConnectionState get getAppConnectionState => _appConnectionState;
  Widget get getRoute {
    return _appConnectionState == MQTTAppConnectionState.connected
        ? MainScreen()
        : LoadingScreen();
  }
}

那么这是我的 main.dart:

import 'package:dnb/services/MQTTAppState.dart';
import 'package:dnb/services/MQTTService.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
void main() => runApp(DigitalNoticeBoard());
class DigitalNoticeBoard extends StatefulWidget {
  @override
  _DigitalNoticeBoardState createState() => _DigitalNoticeBoardState();
}
class _DigitalNoticeBoardState extends State<DigitalNoticeBoard> {
  @override
  void initState() {
    mqttService();
    super.initState();
  }
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData.dark(),
      home: ChangeNotifierProvider(
        create: (_) => MQTTAppState(),
        child: Scaffold(
          body: Consumer<MQTTAppState>(
              builder: (_, mqttAppState, __) => mqttAppState.getRoute),
        ),
      ),
    );
  }
}

正如您在 main.dart 中看到的,我正在 initState() 中启动 mqttService()。当我运行代码时,这就是我得到的:

Performing hot restart...
Syncing files to device POCOPHONE F1...
Restarted application in 1,587ms.
I/flutter (16925): ::Mosquitto client connecting....
E/AccessibilityBridge(16925): VirtualView node must not be the root node.
I/flutter (16925): ::OnConnected client callback - Client connection was sucessful
I/flutter (16925): ::Mosquitto client connected
I/flutter (16925): ::Subscription confirmed -> topic -> topicName
I/flutter (16925): ::Change notification:: topic -> <topicName>, payload ->  <00010000011000000000> 

这是预期的输出,但我的应用卡在加载屏幕中。它打印客户端连接我的应用程序的那一刻应该从加载屏幕移动到主屏幕。 这就是我在 mqttService() 中所做的:

try {
  mqttAppState.setAppConnectionState(MQTTAppConnectionState.connecting); //Passing connecting
  await client.connect();
} on Exception catch (e) {
  print('::client exception - $e');
  //client.disconnect();
}

然后:

/// Check we are connected
if (client.connectionStatus.state == MqttConnectionState.connected) {
  mqttAppState.setAppConnectionState(MQTTAppConnectionState.connected); //Passing connected
  print('::Mosquitto client connected');
} else {
  /// Use status here rather than state if you also want the broker return code.
  print(
      '::ERROR Mosquitto client connection failed - disconnecting, status is ${client.connectionStatus}');
  client.disconnect();
}

【问题讨论】:

    标签: flutter dart widget mqtt flutter-layout


    【解决方案1】:

    @Momshad Dinury

    mqttService()

    try {
      mqttAppState.setAppConnectionState(MQTTAppConnectionState.connecting); //Passing connecting
      await client.connect();
    } on Exception catch (e) {
      print('::client exception - $e');
      //client.disconnect();
    }
    

    这个函数的mqttAppState是什么?

    我认为 create: (_) => MQTTAppState() 中的 MQTTAppState 和你的 mqttAppState 不同。

    你可以试试这个建议:

    MQTTAppState mqttAppState;

      @override
      void initState() {
        mqttAppState = MQTTAppState();
        mqttService();
        super.initState();
      }
    
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          home: ChangeNotifierProvider.value(
            value: mqttAppState,
            child: Scaffold(
              body: Consumer<MQTTAppState>(
                  builder: (_, mqttAppState, __) => mqttAppState.getRoute),
            ),
          ),
        );
      }
    

    【讨论】:

    • mqttAppState = MQTTAppState();这样我就可以访问提供者类的 setAppConnectionState 了。我会尝试你的解决方案并让你知道
    • 它有效。但我不明白。我的意思是:body: Consumer&lt;MQTTAppState&gt;( builder: (_, mqttAppState, __) =&gt; mqttAppState.getRoute),), 如果这里的mqttAppState 不是MQTTAppState 对象的引用,那么它应该给出错误,对吧?但事实并非如此。明确声明参考作品。诡异的!。帮助我了解发生了什么。
    • ChangeNotifierProvider.create 将使用函数 create 创建实例 MQTTAppState 以供 Consumer 使用。所以你调用的mqttService() 上的mqttAppState 不是Provider 的实例MQTTAppState。要解决这个问题。我使用ChangeNotifierProvider.value 只为ProvidermqttService() 共享MQTTAppState 的一个实例。
    • MultiProvider( providers: [ ChangeNotifierProvider&lt;MQTTAppState&gt;(create: (_) =&gt; mqttAppState) ], child: Scaffold( body: Consumer&lt;MQTTAppState&gt;( builder: (_, mqttAppState, __) =&gt; mqttAppState.getRoute), ), ), 这是我后来做的。
    猜你喜欢
    • 2021-01-14
    • 2021-11-29
    • 2020-09-06
    • 2021-07-12
    • 1970-01-01
    • 2022-01-14
    • 2021-01-14
    • 2023-03-22
    • 1970-01-01
    相关资源
    最近更新 更多