Flutter Odoo数据交互插件odoo_repository的使用

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

Flutter Odoo数据交互插件odoo_repository的使用

简介

Odoo Models Repository 是一个用于与Odoo后端通信的抽象层。它帮助在Odoo和Dart客户端之间实现数据通信,并支持持久化和离线模式。

特性

  • 静态类型:Odoo记录使用Dart类型表示。
  • 离线模式:记录存储在本地缓存中。
  • 调用队列:当网络恢复在线时,RPC调用将按顺序执行。
  • 记录流:轻松集成数据更新到BLoC或FutureBuilder中。

描述

Odoo Repository 包使用 OdooRecord 作为基类来表示从远程Odoo实例获取的记录。记录具有以下属性:

  • 存储数据的字段;
  • 不可变;
  • 可以与其他相同类型的记录进行比较;
  • 可以转换为JSON格式。

基本的 res.partner 记录实现

import 'package:equatable/equatable.dart';
import 'package:odoo_repository/odoo_repository.dart';

class Partner extends Equatable implements OdooRecord {
  const Partner(this.id, this.name);

  @override
  final int id;
  final String name;

  /// Converts Partner to JSON
  @override
  Map<String, dynamic> toJson() {
    return {
      'id': id,
      'name': name,
    };
  }

  /// Creates [Partner] from JSON
  static Partner fromJson(Map<String, dynamic> json) {
    return Partner(
      json['id'] as int,
      json['name'] as String,
    );
  }

  /// Equatable stuff to compare records
  @override
  List<Object> get props => [id, name];

  /// List of fields we need to fetch from Odoo
  static List<String> get oFields => ['id', 'name'];

  @override
  String toString() => 'User[$id]: $name';
}

定义 PartnerRepository

每个需要从Odoo获取的模型都需要有自己的 OdooRecordOdooRepository 实现。定义 PartnerRepository 类,该类基于 OdooRepository 并配置为 Partner 类型。

import 'package:odoo_repository/odoo_repository.dart';
import 'package:odoo_rpc/odoo_rpc.dart';
import 'partner_record.dart';

class PartnerRepository extends OdooRepository<Partner> {
  @override
  final String modelName = 'res.partner';

  PartnerRepository(OdooDatabase database) : super(database);

  @override
  Partner createRecordFromJson(Map<String, dynamic> json) {
    return Partner.fromJson(json);
  }
}

初始化 OdooEnvironment

首先需要实例化 OdooEnvironment,它持有Odoo仓库列表并按顺序执行调用队列。

// Init cache storage implemented with Hive
final cache = OdooKvHive();
await cache.init();
// Try to recover session from storage
OdooSession? session = cache.get('cacheSessionKey', defaultValue: null);
const odooServerURL = 'https://my-odoo-instance.com';
final odooClient = OdooClient(odooServerURL, session);
final netConn = NetworkConnectivity();
const odooDbName = 'odoo';

final env = OdooEnvironment(odooClient, odooDbName, cache, netConn);

final partnerRepo = env.add(PartnerRepository(env));
env.add(UserRepository(env));
env.add(SaleOrderRepository(env));
env.add(SaleOrderLineRepository(env));
// and so on
// later we can access instance of PartnerRepository via
final saleOrderRepo = env.of<SaleOrderRepository>();
final saleOrderLineRepo = saleOrderRepo.env.of<SaleOrderLineRepository>();

实现 NetworkConnectivity

可以使用 connectivity 包来实现 NetConnState

import 'package:connectivity/connectivity.dart';
import 'package:odoo_repository/odoo_repository.dart'
    show netConnState, NetConnState;

class NetworkConnectivity implements NetConnState {
  static NetworkConnectivity? _singleton;
  static late Connectivity _connectivity;

  factory NetworkConnectivity() {
    _singleton ??= NetworkConnectivity._();
    return _singleton!;
  }

  NetworkConnectivity._() {
    _connectivity = Connectivity();
  }

  @override
  Future<netConnState> checkNetConn() async {
    final connectivityResult = await (_connectivity.checkConnectivity());
    if (connectivityResult == ConnectivityResult.mobile) {
      return netConnState.online;
    } else if (connectivityResult == ConnectivityResult.wifi) {
      return netConnState.online;
    }
    return netConnState.offline;
  }

  @override
  Stream<netConnState> get onNetConnChanged async* {
    await for (var netState in _connectivity.onConnectivityChanged) {
      if (netState == ConnectivityResult.mobile) {
        // Went online now
        yield netConnState.online;
      } else if (netState == ConnectivityResult.wifi) {
        // Went online now
        yield netConnState.online;
      } else if (netState == ConnectivityResult.none) {
        // Went offline now
        yield netConnState.offline;
      }
    }
  }
}

示例代码

以下是一个完整的示例代码,展示了如何使用 odoo_repository 插件。

import 'dart:io';

import 'package:odoo_repository/odoo_repository.dart' show OdooEnvironment;
import 'package:odoo_rpc/odoo_rpc.dart';
import 'package:user_repository/user_repository.dart';

import 'config.dart';
import 'net_conn_impl.dart';
import 'odoo_kv_hive_impl.dart';

void main() async {
  // Init cache storage implemented with Hive
  final cache = OdooKvHive();
  await cache.init();

  // Try to recover session from storage
  OdooSession? session = cache.get(cacheSessionKey, defaultValue: null);
  // If session is still valid we will be logged in
  final odooClient = OdooClient(odooServerURL, session);
  // Catch session changes to store most recent one
  final sessionChangedHandler = storeSesion(cache);
  odooClient.sessionStream.listen(sessionChangedHandler);

  // Network state tracker is needed by Repository
  final netConn = NetworkConnectivity();

  final env = OdooEnvironment(odooClient, odooDbName, cache, netConn);
  // Alternative way to get instanciated user repo
  // final userRepo = odooEnv.add((db) => UserRepository(db));
  env.add(UserRepository(env));
  final userRepo = env.of<UserRepository>();
  var currentUser = userRepo.records[0];
  print('Current user: ${currentUser.name}');

  final userSub = userRepo.recordStream.listen((user) async {
    if (user[0] != currentUser) {
      if (currentUser.isPublic &&
          !user[0].isPublic &&
          user[0].login == 'admin') {
        print('User changed to ${user[0]}');
        currentUser = user[0];
        // we are logged in
        netConn.goOffline();

        print(
            'In offline mode we still can get record: ${userRepo.records[0]}');

        print('scheduling a rpc call to create new user');
        final newUser = await userRepo.create(User.publicUser()
            .copyWith(login: 'newMe', name: 'New Me', lang: 'uk_UA'));

        print('scheduling a rpc call to rename user that was created');
        await userRepo.write(newUser.copyWith(name: 'New Me!'));
        print('going online');
        netConn.goOnline();
      }
    }
  })
    ..onError((error) => print('User repo error: $error'));

  ProcessSignal.sigint.watch().listen((signal) async {
    print('Exiting...');
    userRepo.logOutUser();
    await userSub.cancel();
    exit(0);
  });

  // Authentication will push new users list to userRepo.recordStream
  await userRepo.authenticateUser(login: 'admin', password: 'admin');
  print('Hit CTRL+c to exit');
  // we need to wait unit async calls will finish
  await Future.delayed(Duration(seconds: 100));
}

问题反馈

如果您遇到任何问题、错误或有功能请求,请在我们的 GitHub 页面上提交。

作者

Odoo Repository LibraryERP Ukraine 开发,Odoo Silver Partner。


更多关于Flutter Odoo数据交互插件odoo_repository的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter Odoo数据交互插件odoo_repository的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,以下是一个关于如何在Flutter应用中使用odoo_repository插件与Odoo进行数据交互的代码案例。odoo_repository是一个用于与Odoo后端进行交互的Flutter插件。这个插件封装了一些常见的Odoo API调用,使得在Flutter应用中集成Odoo变得更加容易。

首先,确保你的Flutter项目中已经添加了odoo_repository依赖。在你的pubspec.yaml文件中添加以下依赖:

dependencies:
  flutter:
    sdk: flutter
  odoo_repository: ^最新版本号 # 替换为最新的版本号

然后运行flutter pub get来获取依赖。

接下来,你需要配置Odoo的连接信息。这通常在你的应用的主文件或配置文件中完成。

import 'package:odoo_repository/odoo_repository.dart';

final OdooRepository odoo = OdooRepository(
  baseUrl: 'https://你的Odoo服务器地址',
  db: '你的数据库名',
  username: '你的Odoo用户名',
  password: '你的Odoo密码',
);

现在,你可以使用odoo_repository插件提供的方法来与Odoo进行交互。例如,获取Odoo中的某个模型的数据:

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

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

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  List<Map<String, dynamic>> partners = [];

  @override
  void initState() {
    super.initState();
    _fetchPartners();
  }

  Future<void> _fetchPartners() async {
    try {
      final result = await odoo.searchRead(
        model: 'res.partner',
        domain: [], // 空域表示获取所有记录
        fields: ['name', 'email'], // 只获取name和email字段
      );
      setState(() {
        partners = result;
      });
    } catch (e) {
      print('Error fetching partners: $e');
    }
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Odoo Partners'),
        ),
        body: ListView.builder(
          itemCount: partners.length,
          itemBuilder: (context, index) {
            final partner = partners[index];
            return ListTile(
              title: Text(partner['name']),
              subtitle: Text(partner['email']),
            );
          },
        ),
      ),
    );
  }
}

在这个例子中,我们创建了一个Flutter应用,它使用odoo_repository插件从Odoo的res.partner模型中获取所有合作伙伴(通常代表联系人或客户)的姓名和电子邮件地址,并在列表中显示它们。

注意几点:

  1. 错误处理:在实际应用中,你应该添加更完善的错误处理机制。
  2. 安全性:不要在客户端代码中硬编码敏感信息(如用户名和密码)。考虑使用环境变量或安全的存储机制。
  3. 性能优化:对于大量数据,考虑分页加载或使用其他优化策略。

这个代码案例应该能够帮助你开始在Flutter应用中使用odoo_repository插件与Odoo进行数据交互。如果你有更具体的需求或遇到问题,可以进一步探索odoo_repository的文档和API。

回到顶部