簡體   English   中英

如何在 Flutter 中正確重用 Provider

[英]How to properly reuse a Provider in Flutter

所以我在我的小部件樹中設置了這個 ChangeNotifierProvider,因為我看到很多子小部件來聆聽它的價值。

我目前正在做的是,每當我要在我的子小部件上重用某些值/函數時,我都會通過構造函數將Provider.of(context)對象從父小部件傳遞給它的子部件。 例如,每次我為我的孩子小部件創建一個Provider.of(context)對象時,它似乎沒有繼承我在父 Provider 上的更新值,而是這個具有我的默認值 null/0/'empty'像它這樣的只是被創造出來的。 這導致我將初始Provider.of(context)對象傳遞給每個將使用 ChangeNotifier 更新值和函數的子級。

這個設置對我有用,但是,當我的小部件樹開始變得復雜時,我不斷地通過每個小部件傳遞值,甚至不使用它的一些小部件只是為了讓它的孩子聽主提供者。

我想我現在可能正在做的是提供者架構的反模式,我希望你們能幫助我以更優化和更有效的方式來做到這一點。

非常感謝!

PS 文檔中的一些內容我還沒有完全掌握。

編輯以下以包含示例代碼和可視化:

provider_type.dart

class ProviderType extends ChangeNotifier{
    String valueA = '';
    String valueB = '';
}

家.dart

import ..provider_type.dart
...
    Widget build(BuildContext context){
        return ChangeNotifierProvider<ProviderType>(
            create: (context) => ProviderType(),
            child: ScreenColumn();
        );
    }
...

screen_column.dart

import ..screen_a.dart
import ..screen_b.dart
class ScreenColumn extends StatelessWidget{
    Widget build(BuildContext context){
        var providerType = Provider.of<ProviderType>(context);

        return Column(
            children: <Widget>[
                ScreenA(providerType: providerType),
                ScreenB(providerType: providerType),
            ],
        );
    }
}

screen_a.dart

class ScreenA extends StatelessWidget{
    final ProviderType providerType;

    ScreenA({this.providerType});

    Widget build(BuildContext context){
        return Text(
            '${providerType.valueA}'
        );
    }
}

screen_b.dart

import ..screen_c.dart
class ScreenB extends StatelessWidget{
    final ProviderType providerType;

    ScreenB({this.providerType});

    Widget build(BuildContext context){
        return ScreenC(providerType: providerType);
    }
}

screen_c.dart

class ScreenC extends StatelessWidget{
    final ProviderType providerType;

    ScreenB({this.providerType});

    Widget build(BuildContext context){
        return Column(
        children: <Widget>[
            Text(
                '${providerType.valueA}'
            )
            Text(
                '${providerType.valueB}'
            )
            Text(
                '${providerType.valueC}'
            )
        ]
        );
    }
}

可視化

在此處輸入圖片說明

所以我目前正在做的是將對象providerType從 ScreenColumn 傳遞到屏幕 A、B 和 C,以便它們每個都具有相同的“值來源”。 因為當我嘗試創建不同的 Provider.of 對象並使用它們時,當我進行一些計算時,它們不會共享相同的更新值。

有什么我可以做的事情來提高效率還是有更好的方法我需要做?

對於那些可能想知道或正在尋找同一問題答案的人,請查看我下面的示例代碼,該代碼顯示了如何在小部件樹中的任何點重用/共享您的 Provider 值和函數,只要它們在您的父項下提供者。

是的,您實際上可以在樹中的任何位置創建 Provider.of 對象,而無需傳遞您創建的初始 Provider.of 對象。

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

class ProviderType extends ChangeNotifier {
  String value = DateTime.now().toString();

  changeValue() {
    value = DateTime.now().toString();
    notifyListeners();
  }
}

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

class AppIndex extends StatelessWidget {
  const AppIndex({
    Key key,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return ChangeNotifierProvider<ProviderType>(
      create: (context) => ProviderType(),
      child: MaterialApp(
        home: Home(),
      ),
    );
  }
}

class Home extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    var providerType = Provider.of<ProviderType>(context);

    return Scaffold(
      appBar: AppBar(
        title: Text('Sample App'),
      ),
      body: ScreenColumn(),
      floatingActionButton: FloatingActionButton.extended(
        onPressed: () => providerType.changeValue(),
        label: Text('ChangeValue'),
      ),
    );
  }
}

class ScreenColumn extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return SingleChildScrollView(
        child: Column(
      crossAxisAlignment: CrossAxisAlignment.stretch,
      children: <Widget>[
        ScreenA(),
        ScreenB(),
        ScreenC(),
        ScreenC(),
      ],
    ));
  }
}

class ScreenA extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    var providerType = Provider.of<ProviderType>(context);
    return Card(
      color: Colors.red,
      elevation: 8.0,
      child: Padding(
        padding: const EdgeInsets.all(16.0),
        child: Text(providerType.value),
      ),
    );
  }
}

class ScreenB extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    var providerType = Provider.of<ProviderType>(context);
    return Card(
      color: Colors.blue,
      elevation: 8.0,
      child: Padding(
        padding: const EdgeInsets.all(16.0),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.stretch,
          children: <Widget>[
            Text(providerType.value),
            ScreenC(),
            ScreenC(),
          ],
        ),
      ),
    );
  }
}

class ScreenC extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // var providerType = Provider.of<ProviderType>(context);

    return Card(
      color: Colors.green,
      elevation: 8.0,
      child: Padding(
        padding: const EdgeInsets.all(16.0),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.stretch,
          children: <Widget>[
            Text('This is Screen B with no Provider.of Object'),
            ScreenD(),
            ScreenD(),
            ScreenD(),
          ],
        ),
      ),
    );
  }
}

class ScreenD extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    var providerType = Provider.of<ProviderType>(context);
    return Card(
      color: Colors.yellow,
      elevation: 8.0,
      child: Padding(
        padding: const EdgeInsets.all(16.0),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.stretch,
          children: <Widget>[
            Text(
                'This is Screen D. A Provider.of object was created here without inheriting the Parent\'s Provider.of object.'),
            Text(providerType.value),
          ],
        ),
      ),
    );
  }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM