【问题标题】:Flutter: Provider and how to update records from the DB in the backgroundFlutter:提供者以及如何在后台更新数据库中的记录
【发布时间】:2021-08-15 23:45:24
【问题描述】:

我是 Flutter 的新手,我有一个简单的用例:在我的 Cloud Firestore 数据库中,我有一个表示事件的 JSON 列表。我想通过我的 Flutter 应用在​​ ListView 中展示它们。

我的要求是ListView 不会实时刷新,而是仅在用户完成拉动式刷新(使用RefreshIndicator 实现)或应用从后台恢复时才刷新

我尝试通过两种方式实现这一点(我正在使用provider 包进行状态管理):

  1. 使用StreamProvider 从数据库创建记录流。这会不断更新列表视图(基本上,小部件会在用户查看它时发生变化,我不希望这样)
  2. 使用一个ChangeNotifierProvider 来引用一个EventManager 类,该类包含一个List<Event>。这个类有一个pull 方法来更新它的内部状态。我在用户进行拉动刷新时调用此方法(在RefreshIndicatoronRefresh 回调中)。

选项 2 似乎运行良好,但我不知道如何在应用程序从后台恢复时实现刷新。正如我所说,我正在使用provider(因此使用StatelessWidget),显然在使用StatelessWidgets 时无法绑定到这些事件

您对此用例有什么建议和最佳实践吗?

【问题讨论】:

    标签: flutter flutter-provider


    【解决方案1】:

    您需要访问 Flutters 生命周期方法并在应用恢复时触发回调。

    您可以使用WidgetsBindingObserver 添加一个有状态小部件并将其放在您的Provider 范围内的某个位置,但作为您用于显示信息的任何小部件的父级。

    或者你可以让你的PullToRefresh 小部件有状态并做同样的事情。

    class LifeCycleWidget extends StatefulWidget {
      @override
      _LifeCycleWidgetState createState() => _LifeCycleWidgetState();
    }
    
    class _LifeCycleWidgetState extends State<LifeCycleWidget>
        with WidgetsBindingObserver {
      AppLifecycleState _appLifecycleState;
    
      @override
      void initState() {
        super.initState();
        WidgetsBinding.instance.addObserver(this);
        refreshOnResume();
      }
    
      @override
      void didChangeAppLifecycleState(AppLifecycleState state) {
        setState(() {
          _appLifecycleState = state;
        });
        refreshOnResume();
      }
    
      void refreshOnResume() {
        if (_appLifecycleState == AppLifecycleState.resumed) {
          print('resumed');
          // your refresh method here
        }
      }
    
      @override
      Widget build(BuildContext context) {
        return HomePage();
      }
    }
    
    

    将以下内容添加到您的 main 方法中,如果它还没有的话。

      WidgetsFlutterBinding.ensureInitialized();
    
    

    不添加有状态小部件的另一种方法是使用GetX。您仍然可以保留所有 Provider 的东西,但只能使用提供生命周期方法的 SuperController。这我无法测试,因为我没有您的 Provider 代码,但您可能可以通过创建下面的类并在相关 Provider 小部件范围内的某处初始化控制器 Get.put(LifeCycleController());

    然后调用onResumed覆盖中的函数,如果需要上下文,可以使用Get.context

    class LifeCycleController extends SuperController {
      @override
      void onDetached() {
        debugPrint('on detached');
      }
    
      @override
      void onInactive() {
        debugPrint('on inactive');
      }
    
      @override
      void onPaused() {
        debugPrint('on pause');
      }
    
      @override
      void onResumed() {
    // your refresh function here. Access context with Get.context
        debugPrint('on resume');
      }
    }
    

    【讨论】:

      猜你喜欢
      • 2021-06-29
      • 2020-07-16
      • 2018-09-06
      • 2019-09-13
      • 1970-01-01
      • 1970-01-01
      • 2020-04-23
      • 2011-11-18
      • 1970-01-01
      相关资源
      最近更新 更多