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

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 的工作机制涉及一个 “服务器” 版本的 SharedStore 或 SharedMap 位于主线程中,负责存储数据。同时,辅助线程中托管着这些共享实例的 “客户端” 版本。

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

注意,主线程是创建 SharedStore 或 SharedMap 实例的线程,而辅助线程是从 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,你可能需要调整代码以适应实际插件的功能和用法。

回到顶部