Flutter共享地图功能插件shared_map的使用

发布于 1周前 作者 eggper 来自 Flutter

Flutter共享地图功能插件shared_map的使用

shared_map简介

shared_map 是一个为Dart应用程序提供同步 Map 数据结构的包。这个包设计用于促进Dart应用程序不同部分之间(包括 Isolate 或外部应用程序)同步键值对的高效共享和通信。

Null Safety Codecov Dart CI GitHub Tag New Commits Last Commits Pull Requests Code size License

动机

  1. 简化共享:在应用的不同部分(尤其是 Isolate )之间共享数据往往很复杂,shared_map 包通过提供共享和同步的映射结构简化了这个过程。
  2. 并发友好:管理并发执行需要仔细考虑数据访问和修改,shared_map 包确保了跨多个执行上下文的安全访问和更新。
  3. 可扩展性:随着应用程序的增长并纳入更多并发模式,拥有可靠的、可扩展的数据共享机制变得至关重要,尤其是在 Isolate 之间。

使用方法

要使用 SharedMap,首先创建一个 SharedStore,然后调用 getSharedMap。要将其传递给另一个 Isolate,可以使用 SharedMap.shareReference() 返回的 SharedReference,然后通过 SharedMap.fromSharedReference(sharedMapReference) 实例化它。

示例代码

以下是一个完整的示例代码,展示了如何使用 shared_map 在主隔离区和辅助隔离区之间共享数据:

import 'dart:io' show exit;
import 'dart:isolate';

import 'package:shared_map/shared_map.dart';

void main() async {
  // 创建 SharedStore
  var store1 = SharedStore('t1');

  // 获取 SharedMap
  var m1 = await store1.getSharedMap<String, int>('m1');

  // 获取不存在的键
  var va1 = await m1!.get('a'); // return `null`
  print('get> va1: $va1');

  // 插入键值对
  var va2 = m1.put('a', 11); // put and return `11`
  print('put> va2: $va2');

  // 获取 SharedMap 的引用
  final sharedMapReference = m1.sharedReference();
  print('sharedMapReference: $sharedMapReference');

  // 在 Isolate 中使用 SharedMap
  var va3 = await Isolate.run<int?>(() async {
    // 从 sharedMapReference 实例化 SharedMap
    var m2 = SharedMap<String, int>.fromSharedReference(sharedMapReference);
    var va3 = await m2.get('a'); // return `11`
    return va3;
  }); // Isolate returns 11

  print('Isolate return> va3: $va3');

  // 在另一个 Isolate 中使用 SharedMap
  var va4 = await Isolate.run<int?>(() async {
    // 从 sharedMapReference 实例化 SharedMap
    var m3 = SharedMap<String, int>.fromSharedReference(sharedMapReference);
    var va4 = await m3.put('a', 111); // put and return 111
    return va4;
  }); // Isolate returns 111

  print('Isolate return> va4: $va4');

  // 获取 SharedMap ID
  final sharedMapID = sharedMapReference.id;
  print('sharedMapID: $sharedMapID');

  // 获取 SharedStore 的引用
  final sharedStoreReference = store1.sharedReference();
  print('shareStoreReference: $sharedStoreReference');

  // 在另一个 Isolate 中使用 SharedStore
  var va5 = await Isolate.run<int?>(() async {
    // 从 shareStoreReference 实例化 SharedStore
    var store2 = SharedStore.fromSharedReference(sharedStoreReference);
    // 通过 SharedStore 获取 SharedMap
    var m4 = await store2.getSharedMap(sharedMapID);
    var va5 = await m4?.put('a', 222); // put and return `222`
    return va5;
  });

  print('Isolate return> va5: $va5'); // print `222`

  // 验证主 Isolate 中的 SharedMap 是否已更新
  var va6 = await m1.get('a');
  print('get> va6: $va6'); // print `222`

  var va7 = await m1.get('a');
  print('get> va7: $va7'); // print `222`

  // 使用 putIfAbsent 方法
  var va8 = await m1.putIfAbsent('a', () => 1001);
  print('putIfAbsent> va8: $va8'); // print `222`

  var va9 = await Isolate.run<int?>(() async {
    var store4 = SharedStore.fromSharedReference(sharedStoreReference);
    var m6 = await store4.getSharedMap(sharedMapID);
    var va9 = await m6?.putIfAbsent('a', () => 1001);
    return va9;
  });

  print('Isolate return> va9: $va9'); // print `222`

  // 插入新键值对
  var vb1 = await m1.putIfAbsent('b', () => 2001);
  print('putIfAbsent> vb1: $vb1'); // print `2001`
  print('get> vb1: ${await m1.get('b')}'); // print `2001`

  var vc1 = await Isolate.run<int?>(() async {
    var store5 = SharedStore.fromSharedReference(sharedStoreReference);
    var m7 = await store5.getSharedMap(sharedMapID);
    var vc1 = await m7?.putIfAbsent('c', () => 3001);
    return vc1;
  });

  print('Isolate return> vc1: $vc1'); // print `3001`
  print('get> vc1: ${await m1.get('c')}'); // print `3001`

  exit(0);
}

输出结果

get> va1: null
put> va2: 11
sharedMapReference: SharedMapReference{id: m1, sharedStore: {id: t1}}
Isolate return> va3: 11
Isolate return> va4: 111
sharedMapID: m1
shareStoreReference: SharedStoreReference{id: t1}
Isolate return> va5: 222
get> va6: 222
get> va7: 222
putIfAbsent> va8: 222
Isolate return> va9: 222
putIfAbsent> vb1: 2001
get> vb1: 2001
Isolate return> vc1: 3001
get> vc1: 3001

工作原理

当在包含 Isolate 的 Dart 平台上操作时,shared_map 的工作机制涉及一个 “服务器” 版本的 SharedStoreSharedMap 位于主线程中,负责存储数据。同时,辅助线程中托管着这些共享实例的 “客户端” 版本。

在辅助线程中,每次对 SharedMap 进行 getput 操作都会触发一个消息发送到 “服务器” 版本,以获取当前值。为了优化性能并避免不必要的线程间请求,建议使用缓存版本的 SharedMap (SharedMapCache)。

注意,主线程是创建 SharedStoreSharedMap 实例的线程,而辅助线程是从 sharedReference 获取实例的线程。

特性和问题反馈

请在 issue tracker 提交功能请求和错误报告。

作者

Graciliano M. Passos: gmpassos@GitHub.

赞助

不要害羞,表达一些爱意,成为我们的 GitHub Sponsor。您的支持对我们意义重大,它让代码保持活力!☕✨

感谢您的支持!🚀😄

许可证

Apache License - Version 2.0


更多关于Flutter共享地图功能插件shared_map的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter共享地图功能插件shared_map的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,下面是一个关于如何在Flutter项目中使用shared_map(假设这是一个提供地图共享功能的插件,尽管实际上Flutter社区中可能没有一个名为shared_map的官方插件,但我会基于一个假设的API结构来展示)的示例代码。请注意,由于具体的插件API和用法可能会有所不同,以下代码仅作为示例,你可能需要根据实际插件的文档进行调整。

1. 添加依赖

首先,在你的pubspec.yaml文件中添加shared_map依赖(假设该插件存在):

dependencies:
  flutter:
    sdk: flutter
  shared_map: ^1.0.0  # 假设的版本号

然后运行flutter pub get来安装依赖。

2. 导入插件

在你的Dart文件中导入shared_map插件:

import 'package:shared_map/shared_map.dart';

3. 初始化地图和共享功能

以下是一个简单的示例,展示如何初始化地图并启用共享功能。假设SharedMap是插件提供的主要类,它有一个init方法来初始化地图,以及一个shareMap方法来共享当前地图状态。

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

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: MapScreen(),
    );
  }
}

class MapScreen extends StatefulWidget {
  @override
  _MapScreenState createState() => _MapScreenState();
}

class _MapScreenState extends State<MapScreen> {
  late SharedMap _sharedMap;

  @override
  void initState() {
    super.initState();
    // 初始化SharedMap实例
    _sharedMap = SharedMap();

    // 初始化地图(假设init方法需要一些配置)
    _sharedMap.init(
      apiKey: 'YOUR_MAP_API_KEY', // 替换为你的地图API密钥
      initialLocation: LatLng(37.7749, -122.4194), // 初始位置,例如旧金山
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Shared Map Example'),
      ),
      body: Stack(
        children: [
          // 显示地图的Widget(假设SharedMap提供了一个build方法返回地图Widget)
          _sharedMap.build(context),
          // 共享按钮
          Positioned(
            bottom: 20,
            right: 20,
            child: ElevatedButton(
              onPressed: () {
                // 共享当前地图状态
                _sharedMap.shareMap().then((result) {
                  // 处理共享结果,例如显示一个Snackbar
                  ScaffoldMessenger.of(context).showSnackBar(
                    SnackBar(content: Text('Map shared: $result')),
                  );
                }).catchError((error) {
                  // 处理错误
                  ScaffoldMessenger.of(context).showSnackBar(
                    SnackBar(content: Text('Failed to share map: $error')),
                  );
                });
              },
              child: Text('Share Map'),
            ),
          ),
        ],
      ),
    );
  }
}

4. 注意事项

  • API密钥:确保你替换了YOUR_MAP_API_KEY为实际的地图服务API密钥。
  • 错误处理:在实际应用中,你应该添加更多的错误处理和用户反馈机制。
  • 插件文档:由于shared_map是一个假设的插件,实际使用时请查阅该插件的官方文档以获取正确的API和用法。

这个示例展示了如何在Flutter应用中集成和使用一个假设的地图共享插件。根据具体插件的API,你可能需要调整代码以适应实际插件的功能和用法。

回到顶部