flutter:Get_Stroage源码01

1,060 阅读2分钟

「这是我参与11月更文挑战的第27天,活动详情查看:2021最后一次更文挑战

背景

昨天我们介绍了一款轻量级的数据持久化的三方Get_Stroage的使用方法,今天我们来看下具体是如何实现的

初始化

昨天我们介绍了当我们想使用Get_Stroage时必须先init一下,或者是创建新的也需要使用init并传入container,所以我们现在看下init中做了什么

static Future<bool> init([String container = 'GetStorage']) {
  WidgetsFlutterBinding.ensureInitialized();
  return GetStorage(container).initStorage;
}

WidgetsFlutterBinding.ensureInitialized()其实就是一个初始化binding的方法,在runApp方法中也有调用,这次我们先不做过多的介绍,之后介绍framework的时候再聊

首先会调用工厂方法判断内存缓存中是否有该容器,如果有则直接取出,如果没有的话,则创建了一个StorageImpl对象并调用init方法,并判断该filename是否存在于html的localStorage,有的话直接读取出来,没有的话直接存入一个


factory GetStorage(
    [String container = 'GetStorage',
    String? path,
    Map<String, dynamic>? initialData]) {
    // 判断内存缓存中是否存在
  if (_sync.containsKey(container)) {
    return _sync[container]!;
  } else {
   // 内存中不存在创建StorageImpl
    final instance = GetStorage._internal(container, path, initialData);
    _sync[container] = instance;
    return instance;
  }
}
GetStorage._internal(String key,
    [String? path, Map<String, dynamic>? initialData]) {
    // 只是创建了一个StorageImpl,init方法在下面
  _concrete = StorageImpl(key, path);
  _initialData = initialData;

  initStorage = Future<bool>(() async {
    await _init();
    return true;
  });
}

Future<void> init([Map<String, dynamic>? initialData]) async {
  subject.value = initialData ?? <String, dynamic>{};
      // 判断本地是否存储未存储则新建,存储了则直接取出
  if (await _exists()) {
    await _readFromStorage();
  } else {
    await _writeToStorage(subject.value!);
  }
  return;
}

到此初始化方法就完成了,创建新Storage也是一样的

增删改查

在使用的时候需要先获取一下单例对象,然后通过单例对象

read

读的时候其实是从ValueStorage中去取出的,这个ValueStorage是继承Get中的ListNotifier,这个我们后续再说

write

写入方法也是通过ValueStorage.value这个map进行写入的,先将数据写入内存中,然后再将数据刷新到磁盘中,这里有两个关键的点,第一个是磁盘刷新的时候出现了一个Microtask(我觉得是一个锁的,防止多次刷新,有懂的大佬可以讲讲),然后第二个就是这里使用到了scheduleMicrotask,scheduleMicrotask的优先级比较高,比Future要高

class Microtask {
  int _version = 0;
  int _microtask = 0;

  void exec(Function callback) {
    if (_microtask == _version) {
      _microtask++;
      scheduleMicrotask(() {
        _version++;
        _microtask = _version;
        callback();
      });
    }
  }
}

remove

先调用ValueStorageremove方法,再调用_tryFlush()刷新磁盘,跟write一样

结语

希望大家把一些好的三方分享出来,打在评论区,共同学习,共同进步

作为Flutter届的一个小学生,希望大家多多指教