Flutter开发进阶之使用Socket实现主机服务(二)

Flutter开发进阶之使用Socket实现主机服务(二)

Flutter开发进阶之使用Socket实现主机服务(一)
在完成局域网内设备定位后就可以进入微服务的实操了。
在这里插入图片描述

I、构建Socket连接池

一、定义Socket

使用socket_io_client

socket_io_client: ^2.0.3+1

导入头文件

import 'package:socket_io_client/socket_io_client.dart' as io;

定义属性

class _SocketIoObject {
  /// 连接
  io.Socket? socket; 
  /// 连接次数
  int count = 0; 
  /// 创建的时间
  int createTime = 0; 
  /// 根据连接频率获取的优先级
  double proportion = 0; 
}

二、定义连接池

class SocketIoPool {
  /// 连接池本身
  static Map<String, dynamic> sockets = {}; 
  /// 连接最大数量
  static int maxCount = 10; 
  /// 根据优先级获取到
  /// 最应该销毁的连接的key
  static String exitKey = ""; 
}

三、连接池运行逻辑

连接排序

/// 将连接按照优先级排序
/// 使用频率越低的连接的优先级越高
/// 可以被销毁
/// 
static void _sortSocket() {
    int now = DateTime.now().millisecondsSinceEpoch;
    double maxProportion = 0;
    sockets.forEach((key, value) {
      value.proportion = (now - value.createTime) / value.count;
      if (value.proportion > maxProportion) {
        maxProportion = value.proportion;
        exitKey = key;
      }
    });
  }

连接创建

/// 创建新连接时限制最大连接数量
/// 
static io.Socket _newSocket(String host, int port) {
    if (sockets.length >= maxCount && exitKey.isNotEmpty) {
      _SocketIoObject? object = sockets[exitKey];
      if (object != null) {
        object.socket?.disconnect();
        object.socket?.dispose();
        sockets.remove(exitKey);
      }
    }
    String relative = "$host:$port";
    io.Socket socket = io.io(relative);
    sockets[relative] = _SocketIoObject()
      ..socket = socket
      ..count = 1
      ..createTime = DateTime.now().millisecondsSinceEpoch;
    Future(() => _sortSocket());
    return socket;
  }

连接获取

/// 尽量复用连接
/// 没有再创建
/// 
static io.Socket? getSocket(String host, int port) {
    String relative = "$host:$port";
    if (sockets.containsKey(relative)) {
      sockets[relative]?.count++;
      Future(() => _sortSocket());
      return sockets[relative]?.socket;
    }
    return _newSocket(host, port);
  }

II、构建数据库

一、对应表的创建

使用sqflite

sqflite: ^2.3.2

导入头文件

import 'package:sqflite/sqflite.dart';

定义表

class Animal {
  int? id;
  int? age;
  double? height;
  int? gender;
  String? name;
  String? species;
  String? family;

  Animal({
    this.id,
    this.age,
    this.height,
    this.gender,
    this.name,
    this.species,
    this.family,
  });
  
  factory Animal.fromJson(Map<String, dynamic> map) {
    return Animal(
        id: map["id"],
        age: map["age"],
        height: map["height"],
        gender: map["gender"],
        name: map["name"],
        species: map["species"],
        family: map["family"]);
  }
  
  /// 类名
  static String className<T>() {
    return T.toString();
  }
  
  /// 创建表
  static Future<void> createTable(Database db) async {
    final batch = db.batch();
    batch.execute(createTableSql);
    await batch.commit();
  }
}

注意:为提高并发性能,尽量使用事务管理,

When committed with [Batch.commit], sqflite will manage a transaction to
execute statements in the batch. If this [batch] method has been called on a [Transaction], committing the batch is deferred to when the transaction
completes (but [Batch.apply] or [Batch.commit] still need to be called).

体现在sqflite中就是使用Batch或者transaction。

二、定义sql语句

/// 插入数据
  String get insertSql =>
      "INSERT OR REPLACE INTO ${Animal.className()} (id,age,height,gender,name,species,family) VALUES ($id,$age,$height,$gender,$name,$species,$family)";

  /// 更新数据
  String get updateSql =>
      "UPDATE ${Animal.className()} SET age = $age, height = $height, gender = $gender, name = $name, species = $species, family = $family WHERE id = $id";

  /// 删除数据
  String get deleteSql => "DELETE FROM ${Animal.className()} WHERE id = $id";

  /// 查询所有
  static String get allSql => "SELECT * FROM ${Animal.className()}";

  /// 删除表
  static String get clearSql => "DROP TABLE ${Animal.className()}";

  /// 查询某条
  static String get oneSql =>
      "SELECT * FROM ${Animal.className()} WHERE id = ?";

三、定义数据库管理器

class SqfliteManager {
  /// 数据库名称 一般为xx.db
  String dbName;
  /// 数据库版本
  int version;

  SqfliteManager({
    required this.dbName,
    required this.version,
  });
}

数据库的获取

  Database? _database;

  Future<String> get _databasePath async {
    final databasePath = await getDatabasesPath();
    return "$databasePath/$dbName";
  }

  /// 获取数据库
  Future<Database?> get database async {
    if (_database == null) {
      String path = await _databasePath;
      _database =
          await openDatabase(path, version: version, onCreate: (db, v) async {
        /// 创建数据库时
      }, onConfigure: (db) {
        /// 数据库配置时,在创建前、升降级前
      }, onDowngrade: (db, oldV, newV) {
        /// 数据库降级时
      }, onUpgrade: (db, oldV, newV) {
        /// 数据库升级时
      }, onOpen: (db) {
        /// 数据库打开时
      });
    }
    return _database;
  }

四、对应的数据库操作指令

/// 销毁数据库
  Future<void> cancelDatabase() async {
    String path = await _databasePath;
    return deleteDatabase(path);
  }

  /// 数据库关闭
  Future<void> closeDatabase() async {
    if (_database?.isOpen == true) {
      await _database?.close();
    }
    _database = null;
  }

  /// 插入动物数据
  Future<void> insertAnimal(Animal animal) async {
    await database.then(
      (db) async => await db?.transaction(
        (txn) async => await txn.rawInsert(animal.insertSql),
      ),
    );
  }

  /// 更新动物数据
  Future<void> updateAnimal(Animal animal) async {
    await database.then(
      (db) async => await db?.transaction(
        (txn) async => await txn.rawUpdate(animal.updateSql),
      ),
    );
  }

  /// 删除动物数据
  Future<void> deleteAnimal(Animal animal) async {
    await database.then(
      (db) async => await db?.transaction(
        (txn) async => await txn.rawDelete(animal.deleteSql),
      ),
    );
  }

  /// 查询所有动物数据
  Future<List<Animal>?> allAnimals() async {
    final db = await database;
    final batch = db?.batch();
    batch?.rawQuery(Animal.allSql);
    List<Map<String, dynamic>>? maps =
        await batch?.commit() as List<Map<String, dynamic>>?;
    return maps?.map((e) => Animal.fromJson(e)).toList();
  }

  /// 删除动物数据表
  Future<void> deleteAnimalTable() async {
    await database.then(
      (db) async => await db?.transaction(
        (txn) async => await txn.rawDelete(Animal.clearSql),
      ),
    );
  }

  /// 查询单条动物数据
  Future<Animal?> findAnimal(int id) async {
    final db = await database;
    final batch = db?.batch();
    batch?.rawQuery(Animal.oneSql, [id]);
    List<Map<String, dynamic>>? maps =
        await batch?.commit() as List<Map<String, dynamic>>?;
    return maps?.map((e) => Animal.fromJson(e)).toList().first;
  }

III、执行通讯

    final a = SocketIoPool.getSocket('http://192.168.0.1', 80);
    a?.connect();
    a?.on('getAnimals', (data) {
      a.emit('getAnimalsResponse', {data: animals});
    });
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Kevin写代码

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值