首页 > 其他分享 >Provider的八种提供者

Provider的八种提供者

时间:2023-12-30 10:23:13浏览次数:29  
标签:return name 提供者 Provider 八种 book context child class

代码

class Example extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text("Example"),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            // 使用Consumer部件获取UserModel实例并订阅其变化
            Consumer<UserModel>(
              builder: (_, userModel, child) {
                // 在数据更新时,重新构建子部件,并显示userModel的name属性
                return Text(userModel.name,
                    style: const TextStyle(
                        color: Colors.red,
                        fontSize: 30
                    )
                );
              },
            ),
            // 使用Consumer部件获取UserModel实例并订阅其变化
            Consumer<UserModel>(
              builder: (_, userModel, child) {
                // 在数据更新时,重新构建子部件,并显示一个按钮,点击按钮会调用changeName方法改变name的值
                return Padding(
                  padding: const EdgeInsets.all(20),
                  child: ElevatedButton(
                    onPressed: (){
                      userModel.changeName();
                    },
                    child: const Text("改变值"),
                  ),
                );
              },
            ),
          ],
        ),
      ),
    );
  }
}

1、Provider:

通用的提供者,可用于共享任何对象,不仅仅是状态对象。在更新时,提供者会重新构建依赖于该对象的部件。

创建模型
//1 最基本的Provider组件,可以使用它为组件树中的任何位置提供值,
//组件但是当该值更改的时候,它并不会更新UI
class UserModel   extends ChangeNotifier {
  String name = "jimi";

  void changeName(){
    name = "hellp";
    print(name);
  }
}
应用程序入口设置
class MyApp9 extends StatelessWidget {
  const MyApp9({super.key});

  @override
  Widget build(BuildContext context) {
    return    Provider<UserModel>(
      create: (_) =>UserModel(),
      child:  MaterialApp(
        debugShowCheckedModeBanner: false,
        home: Example(),
      ),   
      );
  }
}

2、* ChangeNotifierProvider:

用于将一个ChangeNotifier对象共享给其子孙节点,并监听状态变化。会监听模型对象的变化,而且当数据改变时,它也会重建Consumer(消费者)

创建模型
//2.ChangeNotifierProvider 它跟Provider组件不同,
//ChangeNotifierProvider会监听模型对象的变化,而且当数据改变时,
//它也会重建Consumer(消费者)
class UserModel with ChangeNotifier {

  String name = "Jimi";

  void changeName() {
    name = "hello";
    notifyListeners();
  }
}
应用程序入口设置
class MyApp9 extends StatelessWidget {
  const MyApp9({super.key});

  @override
  Widget build(BuildContext context) {
    return ChangeNotifierProvider<UserModel>(
      create: (_) =>UserModel(),
      child:  MaterialApp(
        debugShowCheckedModeBanner: false,
        home: Example(),
      ),
      
      );
  }
}
 

3、FutureProvider:

用于共享Future对象,通常在异步操作和数据加载中使用。

  • FutureProvider只会重建一次
  • 默认显示初始值
  • 然后显示Future
  • 最后不会再次重建
创建模型
class UserModel {

  UserModel({required this.name});

  String name = "Jimi";

  Future<void> changeName() async {
    print(name);
    await Future.delayed(const Duration(milliseconds: 2000)); //模拟网络请求延迟两秒后改变其值
    name = "hello";
    print(name);
  }
}
class UserFuture {
  Future<UserModel> asyncGetUserModel2() async {
    await Future.delayed(const Duration(milliseconds: 6000));
    return UserModel(name: "获取新的数据");
  }
}
应用程序入口设置
class MyApp9 extends StatelessWidget {
  const MyApp9({super.key});

  @override
  Widget build(BuildContext context) {
    return    FutureProvider<UserModel>(
      create: (_) =>UserFuture().asyncGetUserModel2(),
      initialData: UserModel(name: "hello1"),  //必传 不传报错
      child:  MaterialApp(
        debugShowCheckedModeBanner: false,
        home: Example(),
      ),
      );
  }
}

4、StreamProvider:

用于共享流(Stream)对象,可以是Dart中的任何流。和FutureProvider一样,主要的区别在于值会根据多次触发重新构建UI。

创建模型
//4、StreamProvider提供流值,是围绕StreamBuilder,所提供的值会在传入的时候替换掉新值。
//和FutureProvider一样,主要的区别在于值会根据多次触发重新构建UI。
class UserModel {
 UserModel({required this.name});
  String name = "Jimi";

  void changeName() {
    name = "hello";
  }
}

//每隔一秒钟生成一个数字
class UserStream {

  Stream<UserModel> getStreamUserModel() {
    return Stream<UserModel>.periodic(const Duration(milliseconds: 1000),
        (value) => UserModel(name: "$value")
    ).take(10);
  }
}
应用程序入口设置
class MyApp9 extends StatelessWidget {
  const MyApp9({super.key});

  @override
  Widget build(BuildContext context) {
    return    StreamProvider<UserModel>(
      create: (_) => UserStream().getStreamUserModel(),
      initialData: UserModel(name: "hello1"),  //必传 不传报错
      child:  MaterialApp(
        debugShowCheckedModeBanner: false,
        home: Example(),
      ),
      );
  }
}

5、* MultiProvider

在实际开发过程中肯定会有多个提供者,我们虽然可以采用嵌套的方式来解决,但是这样无疑是混乱的,

可读性级差。这个时候强大的MultiProvder就产生了;用于在应用程序的根部层次上为子树中的多个小部件提供数据共享;

创建模型
class UserModel1 with ChangeNotifier {

  String name = "Jimi";

  void changeName() {
    name = "hello";
    notifyListeners();
  }
}

class UserModel4 with ChangeNotifier {

  String name = "Jimi";
  int age = 18;

  void changeName() {
    name = "hello";
    age = 20;
    notifyListeners();
  }
}
应用程序入口设置
return MultiProvider(
  providers: [
    ChangeNotifierProvider<UserModel1>(create: (_) => UserModel1()),
    ChangeNotifierProvider<UserModel4>(create: (_) => UserModel4()),
    /// 添加更多
  ],
  child: MaterialApp(
    debugShowCheckedModeBanner: false,
    home: MultiProviderExample(),
  ),
);
使用数据
class MultiProviderExample extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("MultiProviderExample"),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Consumer<UserModel1>(
              builder: (_, userModel, child) {
                return Text(userModel.name,
                    style: TextStyle(
                        color: Colors.red,
                        fontSize: 30
                    )
                );
              },
            ),
            Consumer<UserModel4>(
              builder: (_, userModel, child) {
                return Text(userModel.age.toString(),
                    style: TextStyle(
                        color: Colors.green,
                        fontSize: 30
                    )
                );
              },
            ),
            Consumer2<UserModel1, UserModel4>(
              builder: (_, userModel1, userModel4, child) {
                return Padding(
                  padding: EdgeInsets.all(20),
                  child: ElevatedButton(
                    onPressed: (){
                      userModel1.changeName();
                      userModel4.changeName();
                    },
                    child: Text("改变值"),
                  ),
                );
              },
            ),
          ],
        ),
      ),
    );
  }
}

6、ProxyProvider:

用于根据其他提供者的值计算新值,并将新值共享给下游部件。

当我们有多个模型的时候,会有模型依赖另一个模型的情况,在这种情况下,

我们可以使用ProxyProvider从另一个提供者获取值,然后将其注入到另一个提供者中。

创建模型
class UserModel5 with ChangeNotifier {

  String name = "Jimi";

  void changeName({required String newName}) {
    name = newName;
    notifyListeners();
  }
}


class WalletModel {

  UserModel5? userModel5;

  WalletModel({this.userModel5});

  void changeName() {
    userModel5?.changeName(newName: "JIMI");
  }
}
应用程序入口设置
class MyApp9 extends StatelessWidget {
  const MyApp9({super.key});

  @override
  Widget build(BuildContext context) {
return MultiProvider(
  providers: [
    ChangeNotifierProvider<UserModel5>(create: (_) => UserModel5()),
    ProxyProvider<UserModel5, WalletModel>(
      update: (_, userModel5, walletModel) => WalletModel(userModel5: userModel5),
    )
  ],
  child: MaterialApp(
    debugShowCheckedModeBanner: false,
    home: ProxyProviderExample(),
  ),
);
  }
}
使用数据
class ProxyProviderExample extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("ProxyProviderExample"),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Consumer<UserModel5>(
              builder: (_, userModel, child) {
                return Text(userModel.name,
                    style: const TextStyle(
                        color: Colors.red,
                        fontSize: 30
                    )
                );
              },
            ),
            Consumer<UserModel5>(
              builder: (_, userModel, child) {
                return Padding(
                  padding: EdgeInsets.all(20),
                  child: ElevatedButton(
                    onPressed: (){
                      userModel.changeName(newName: "hello");
                    },
                    child: Text("改变值"),
                  ),
                );
              },
            ),
            Consumer<WalletModel>(
              builder: (_, walletModel, child) {
                return Padding(
                  padding: EdgeInsets.all(20),
                  child: ElevatedButton(
                    onPressed: (){
                      walletModel.changeName();
                    },
                    child: Text("通过代理改变值"),
                  ),
                );
              },
            ),
          ],
        ),
      ),
    );
  }
}

7、* ChangeNotifierProxyProvider

ProxyProvider原理一样,唯一的区别在于它构建和同步ChangeNotifierChangeNotifierProvider,当提供者数据变化时,将会重构UI。

创建模型

1.

class BookModel {
  
  static var _books = [
    Book(1, "夜的命名数"),
    Book(2, "大奉打更人"),
    Book(3, "星门"),
    Book(4, "大魏读书人"),
    Book(5, "我师兄实在太稳健了"),
    Book(6, "深空彼岸"),
  ];

  // 获取书籍长度
  int get length => _books.length;

  // 根据ID获取书籍
  Book getById(int id) => _books[id -1];

  // 根据索引获取数据
  Book getByPosition(int position) => _books[position];

  // 更多....
}

class Book {
  final int bookId;
  final String bookName;
  
  Book(this.bookId, this.bookName);
}

2.

class BookManagerModel with ChangeNotifier {

  // 依赖bookModel
  final BookModel _bookModel;

  // 获取数据所有的ID
  List<int>? _bookIds;

  // 构造函数
  BookManagerModel(this._bookModel, {BookManagerModel? bookManagerModel})
    : _bookIds = bookManagerModel?._bookIds ?? [];

  // 获取所有的书
  List<Book> get books => _bookIds!.map((id) => _bookModel.getById(id)).toList();

  // 根据索引获取数据
  Book getByPosition(int position) => books[position];

  // 获取书籍的长度
  int get length => _bookIds?.length ?? 0;

  // 添加书籍
  void addFaves(Book book) {
    _bookIds!.add(book.bookId);
    notifyListeners();
  }

  // 删除书籍
  void removeFaves(Book book) {
    _bookIds!.remove(book.bookId);
    notifyListeners();
  }
}
复制代码
应用程序入口设置
return MultiProvider(
  providers: [
    Provider(create: (_) => BookModel()),
    ChangeNotifierProxyProvider<BookModel, BookManagerModel>(
      create: (_) => BookManagerModel(BookModel()),
      update: (_, bookModel, bookManagerModel) => BookManagerModel(bookModel),
    )
  ],
  child: MaterialApp(
    debugShowCheckedModeBanner: false,
    home: ChangeNotifierProxyProviderExample(),
  ),
);
使用数据

1.

class ChangeNotifierProxyProviderExample extends StatefulWidget {
  @override
  _ChangeNotifierProxyProviderExampleState createState() => _ChangeNotifierProxyProviderExampleState();
}

class _ChangeNotifierProxyProviderExampleState extends State<ChangeNotifierProxyProviderExample> {


  var _selectedIndex = 0;
  var _pages = [PageA(), PageB()];

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: _pages[_selectedIndex],
      bottomNavigationBar: BottomNavigationBar(
        currentIndex: _selectedIndex,
        onTap: (index) {
          setState(() {
            _selectedIndex = index;
          });
        },
        items: [
          BottomNavigationBarItem(
            icon: Icon(Icons.book),
            label: "书籍列表"
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.favorite),
            label: "收藏"
          )
        ],
      ),
    );
  }
}

2.

class PageA extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    
    var bookModel = Provider.of<BookModel>(context);
    
    return Scaffold(
      appBar: AppBar(
        title: Text("书籍列表"),
      ),
      body: ListView.builder(
        itemCount: bookModel.length,
        itemBuilder: (_, index) => BookItem(id: index + 1),
      ),
    );
  }
}

3.

class PageB extends StatelessWidget {
  @override
  Widget build(BuildContext context) {

    var bookManagerModel = Provider.of<BookManagerModel>(context);
    var bookCount = bookManagerModel.length;

    return Scaffold(
      appBar: AppBar(
        title: Text("收藏列表"),
      ),
      body: ListView.builder(
        itemCount: bookCount,
        itemBuilder: (_, index) => BookItem(id: bookManagerModel.getByPosition(index).bookId),
      ),
    );
  }
}

4.

class BookButton extends StatelessWidget {
  
  final Book book;
  
  BookButton({
    Key? key,
    required this.book
  }) : super(key: key);
  
  @override
  Widget build(BuildContext context) {
    
    var bookManagerModel = Provider.of<BookManagerModel>(context);
    
    return GestureDetector(
      onTap: bookManagerModel.books.contains(this.book)
          ?  () => bookManagerModel.removeFaves(this.book)
          :  () => bookManagerModel.addFaves(this.book),
      child: SizedBox(
        width: 100,
        height: 60,
        child: bookManagerModel.books.contains(this.book)
            ?  Icon(Icons.star, color: Colors.red,)
            :  Icon(Icons.star_border),
      ),
    );
  }
}

5.

class BookItem extends StatelessWidget {

  final int id;

  BookItem({
    Key? key,
    required this.id
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {

    var bookModel = Provider.of<BookModel>(context);
    var book = bookModel.getById(id);

    return ListTile(
      leading: CircleAvatar(
        child: Text("${book.bookId}"),
      ),
      title: Text("${book.bookName}",
        style: TextStyle(
            color: Colors.black87
        ),
      ),
      trailing: BookButton(book: book),
    );
  }
}

ListenableProxyProvider:

ListenableProxyProviderListenableProvider的一个变体,但是在使用上和ChangeNotifierProvider效果惊人的一致

 

此参考于Flutter Provider状态管理---八种提供者使用分析-腾讯云开发者社区-腾讯云 (tencent.com)

 

标签:return,name,提供者,Provider,八种,book,context,child,class
From: https://www.cnblogs.com/xbinbin/p/17935581.html

相关文章

  • 安卓之DocumentsProvider应用场景以及优劣分析
    文章摘要本文深入探讨了安卓DocumentsProvider的应用场景,分析了其优势与不足,并提供了简单的代码实现。DocumentsProvider是安卓系统中用于文件存储与访问的关键组件,为应用开发者提供了强大的文件管理能力。正文DocumentsProvider概述DocumentsProvider是安卓系统中的一个组件,允许应......
  • 安卓之DocumentsProvider应用场景以及优劣分析
    文章摘要本文深入探讨了安卓DocumentsProvider的应用场景,分析了其优势与不足,并提供了简单的代码实现。DocumentsProvider是安卓系统中用于文件存储与访问的关键组件,为应用开发者提供了强大的文件管理能力。正文DocumentsProvider概述DocumentsProvider是安卓系统中的......
  • Nestjs的Provider 和依赖注入
    前言上文介绍了如何理解依赖注入和控制反转,简单来说,控制反转是一种设计模式,可以将类与类的关系解耦,将人工维护转移给一个容器维护。要实现控制反转,依赖注入是一个常用方案,将依赖注册到DI容器中,哪里用到,就让容器将实例注入到哪里。Nest中的依赖注入,主要就是围绕提供者(Provider)展......
  • springcloudalibabada搭建过程中springboot启动卡住起不来 (Started MoonceProviderApp
    如下图一样springcloudAlibaba在创建新模块之后启动新模块没有注册到nacos上,而是直接卡住起不来原因 原因是:引入了错误的web包: 解决办法:引入相应的 spring-boot-starter-web包:<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot......
  • 自定义session Provider随笔[由多个请求阻塞排队处理发现]
    引用:Session,有没有必要使用它?usingIDH.Common.BaseInfoCacheManagement;usingNewtonsoft.Json;usingSystem;usingSystem.Collections.Generic;usingSystem.Collections.Specialized;usingSystem.Web;usingSystem.Web.SessionState;namespaceIdhWebApplication.E......
  • 在.net中通过自定义LoggerProvider将日志保存到数据库方法(以mysql为例)
     在.NET中,Microsoft.Extensions.Logging是一个灵活的日志库,它允许你将日志信息记录到各种不同的目标,包括数据库。在这个示例中,我将详细介绍如何使用Microsoft.Extensions.Logging将日志保存到MySQL数据库。我们将使用EntityFrameworkCore来与MySQL数据库进行交互。步骤一:创......
  • ContentProvider 之 写入联系人数据
    在项目ContentProviderSample代码基础上实现写入共享联系人数据的示例,具体步骤如下:在AndroidManifest.xml中,添加写入联系人数据的权限编辑布局文件activity_contacts.xml,界面上布局三个文本输入框用于填写联系人名称、电话号码和邮箱账号和确认写入按钮。编写代码ContactsActivi......
  • PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderExce
    由于接口是HTTPS,本地没有证书,导致报PKIXpathbuildingfailed:sun.security.provider.certpath.SunCertPathBuilderException:unabletofindvalidcertificationpathtorequestedtarget导出证书Chrome浏览器导出HTTPS证书创建一个Java信任库创建一个Java信任库(Trusts......
  • .NET之默认依赖注入 注入方式(构造函数注入、FromServices操作注入)和 获取服务(Contr
    .NET之默认依赖注入注入方式(构造函数注入、FromServices操作注入)和获取服务(Controller构造函数中注入获取、IServiceProvider获取、statrup中获取服务)介绍领券https://www.cps3.cn/不要依赖于具体的实现,应该依赖于抽象,高层模块不应该依赖于底层模块,二者应该依赖于抽......
  • Android FileProvider的一些事
    高版本的android对文件权限的管控抓的很严格,理论上两个应用之间的文件传递现在都应该是用FileProvider去实现,这篇博客来一起了解下它的实现原理。首先我们要明确一点,FileProvider就是一个ContentProvider,所以需要在AndroidManifest.xml里面对它进行声明:<providerandroid:......