flutter 利用provider和Store 管理共享状态

需求:在登陆完成后需要缓存登录返回的信息 例如 字典对象,这些信息在我的页面有进行使用例如展示用户的名字等

技术要点:Provider Store ChangeNotifier 等

实现方式:

001 新建一个登陆页面的Provider

import 'package:flutter/foundation.dart';
import 'package:qianduoduo/models/login_model.dart';
import 'package:shared_preferences/shared_preferences.dart';

class LoginPageProvider with ChangeNotifier {
  bool _isLogin = false;
  get isLogin => _isLogin;

  String _verifyStr = '获取验证码';
  get verifyStr => _verifyStr;

  /// 是否可以获取验证码,默认为`false`。
  bool _available = true;
  get available => _available;

  changeLoginState(bool login) {
    _isLogin = login;
    notifyListeners();
  }

  changeVerifyStr(String verifyStr, bool available) {
    _available = available;
    _verifyStr = verifyStr;
    notifyListeners();
  }

  LoginModel _getSMS;
  get getSMS => _getSMS;

  LoginModel _loginModel;
  get loginModel => _loginModel;

  changeLoginData(data) {
    _loginModel = LoginModel.fromJson(data);
    notifyListeners();
  }

  String _phone;
  get phone => _phone;

  savePhone(phone) async {
    SharedPreferences prefs = await SharedPreferences.getInstance();
    if (phone == null) {
      phone = prefs.getString('phone');
    }
    _phone = phone;
    prefs.setString('phone', phone);
    notifyListeners();
  }



  @override
  void dispose() {
    super.dispose();
  }
}

002 将登陆返回的信息缓存起来

   LoginPageProvider loginPageProvider =
        Store.value<LoginPageProvider>(context);
    loginPageProvider.changeLoginData(resultModel.data);
 Store.value<OrderProvider>(context)
                                      .takeOrderSuccess(
                                          false, cardDataDetail.data.orderNo);

003 在我的页面拿到这个信息,如果有改变就立即通知其他页面。类似于IOS 通知机制

    //显示正常
    return Store.connect<LoginPageProvider>(
        builder: (context, LoginPageProvider provider, child) {
      LoginModel loginModel = provider.loginModel;
      return Container()})
  @override
  Widget build(BuildContext context) {
    return Container(
      child: Store.connect<OrderProvider>(
          builder: (context, orderProvider, child) {
        print('选择了$context');
        //监听订单抢单成功通知 跳转到第二个Tab页面

        if (orderProvider.orderNo != null && orderProvider.orderNo.length > 0) {
          currentIndex = 1;
          //清空orderNo 恢复正常currentIndex
          Store.value<OrderProvider>(context).takeOrderSuccess(false, '');
        }

        return Scaffold();
}),
);

005 Store管理类

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

import 'package:qianduoduo/provider/login_page_provider.dart';

class Store {
  static BuildContext context;
  static BuildContext widgetCtx;

  //  我们将会在main.dart中runAPP实例化init
  static init({context, child}) {
    return MultiProvider(
      providers: [
        ChangeNotifierProvider(builder: (_) => LoginPageProvider()),
      ],
      child: child,
    );
  }

  //  通过Provider.value<T>(context)获取状态数据
  static T value<T>(context) {
    return Provider.of(context, listen: false);
  }

  //  通过Consumer获取状态数据
  static Consumer connect<T>({builder, child}) {
    return Consumer<T>(builder: builder, child: child);
  }
}

004 ChangeNotifier官方文档说明

A class that can be extended or mixed in that provides a change notification API using VoidCallback for notifications.

It is O(1) for adding listeners and O(N) for removing listeners and dispatching notifications (where N is the number of listeners).

一个可以被拓展或者多继承的类,提供一个改变的通知,使用无符号回调通知。添加监听是O(1)时间复杂度,移除或者执行通知是O(N)的时间复杂度

005 ChangeNotifier 源码解析

ChangeNotifier继承Listenable 

class ChangeNotifier implements Listenable {
  LinkedList<_ListenerEntry>? _listeners = LinkedList<_ListenerEntry>();

有个链表类型的属性istener。

几个关键的方法

001 添加监听

  @override
  void addListener(VoidCallback listener) {
    assert(_debugAssertNotDisposed());
    _listeners!.add(_ListenerEntry(listener));
  }

002 移除监听

  @override
  void removeListener(VoidCallback listener) {
    assert(_debugAssertNotDisposed());
    for (final _ListenerEntry entry in _listeners!) {
      if (entry.listener == listener) {
        entry.unlink();
        return;
      }
    }
  }

003 释放监听

  @mustCallSuper
  void dispose() {
    assert(_debugAssertNotDisposed());
    _listeners = null;
  }

 

查看LinkedList源码

 /// Adds [entry] to the beginning of the linked list.
  void addFirst(E entry) {
    _insertBefore(_first, entry, updateFirst: true);
    _first = entry;
  }

  /// Adds [entry] to the end of the linked list.
  void add(E entry) {
    _insertBefore(_first, entry, updateFirst: false);
  }

  /// Add [entries] to the end of the linked list.
  void addAll(Iterable<E> entries) {
    entries.forEach(add);
  }

  /// Removes [entry] from the linked list.
  ///
  /// Returns false and does nothing if [entry] is not in this linked list.
  ///
  /// This is equivalent to calling `entry.unlink()` if the entry is in this
  /// list.
  bool remove(E entry) {
    if (entry._list != this) return false;
    _unlink(entry); // Unlink will decrement length.
    return true;
  }

006 参考文献:

ChangeNotifier

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值