Flutter远程过程调用插件kangaroo_rpc的使用

Flutter远程过程调用插件kangaroo_rpc的使用

特性

  • 使用之前存储的Odoo会话初始化客户端。
  • 通过数据库名称、登录名和密码进行身份验证。
  • 向JSON控制器发出JSON-RPC请求。
  • 通过CallKw执行公共方法。
  • 通过流获取Odoo会话更新。
  • 终止会话(登出)。
  • 在会话过期时捕获异常。

使用

要使用此插件,在您的pubspec.yaml文件中添加kangaroo_rpc作为依赖项。例如:

dependencies:
  kangaroo_rpc: ^0.4.5

示例

基本RPC调用

import 'dart:io';
import 'package:kangaroo_rpc/kangaroo_rpc.dart';

void main() async {
  final client = OdooClient('https://my-db.odoo.com');
  try {
    await client.authenticate('my-db', 'admin', 'admin');
    final res = await client.callKw({
      'model': 'res.users',
      'method': 'search_read',
      'args': [],
      'kwargs': {
        'context': {'bin_size': true},
        'domain': [],
        'fields': ['id', 'name', '__last_update'],
      },
    });
    print('User info: \n' + res.toString());
  } on OdooException catch (e) {
    print(e);
    client.close();
    exit(-1);
  }
  client.close();
}

带有跟踪会话变化的RPC调用

Odoo服务器将在每次调用时发出新的session_id

import 'dart:io';
import 'package:kangaroo_rpc/kangaroo_rpc.dart';

void sessionChanged(OdooSession sessionId) async {
  print('We got new session ID: ${sessionId.id}');
  // 将会话ID写入持久存储
}

void main() async {
  // 从存储中恢复会话ID并传递给客户端构造函数
  final baseUrl = 'https://demo.odoo.com';
  final client = OdooClient(baseUrl);

  // 订阅会话变化以存储最新的会话
  var subscription = client.sessionStream.listen(sessionChanged);

  try {
    // 使用数据库名称和凭据对服务器进行身份验证
    final session = await client.authenticate('odoo', 'admin', 'admin');
    print(session);
    print('Authenticated');

    // 根据服务器版本计算图像字段名称
    final imageField = session.serverVersionInt >= 13 ? 'image_128' : 'image_small';

    // 读取用户字段
    final uid = session.userId;
    var res = await client.callKw({
      'model': 'res.users',
      'method': 'search_read',
      'args': [],
      'kwargs': {
        'context': {'bin_size': true},
        'domain': [
          ['id', '=', uid]
        ],
        'fields': ['id', 'name', '__last_update', imageField],
      },
    });
    print('\nUser info: \n' + res.toString());

    // 如果收到回复,计算头像URL
    if (res.length == 1) {
      var unique = res[0]['__last_update'] as String;
      unique = unique.replaceAll(RegExp(r'[^0-9]'), '');
      final userAvatar = '$baseUrl/web/image?model=res.user&field=$imageField&id=$uid&unique=$unique';
      print('User Avatar URL: $userAvatar');
    }

    // 创建合作伙伴
    var partnerId = await client.callKw({
      'model': 'res.partner',
      'method': 'create',
      'args': [
        {
          'name': 'Stealthy Wood',
        },
      ],
      'kwargs': {},
    });

    // 通过ID更新合作伙伴
    res = await client.callKw({
      'model': 'res.partner',
      'method': 'write',
      'args': [
        partnerId,
        {
          'is_company': true,
        },
      ],
      'kwargs': {},
    });

    // 获取已安装模块列表
    res = await client.callRPC('/web/session/modules', 'call', {});
    print('\nInstalled modules: \n' + res.toString());

    // 检查是否已登录
    print('\nChecking session while logged in');
    res = await client.checkSession();
    print('ok');

    // 登出
    print('\nDestroying session');
    await client.destroySession();
    print('ok');
  } on OdooException catch (e) {
    // 处理Odoo异常时的清理工作
    print(e);
    await subscription.cancel();
    client.close();
    exit(-1);
  }

  print('\nChecking session while logged out');
  try {
    var res = await client.checkSession();
    print(res);
  } on OdooSessionExpiredException {
    print('Odoo Exception:Session expired');
  }
  await client.inRequestStream.isEmpty;
  await subscription.cancel();
  client.close();
}

Flutter示例

使用FutureBuilder的Flutter示例。

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

final orpc = OdooClient('https://my-odoo-instance.com');

void main() async {
  await orpc.authenticate('odoo-db', 'admin', 'admin');
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: HomePage(),
    );
  }
}

class HomePage extends StatelessWidget {
  Future<dynamic> fetchContacts() {
    return orpc.callKw({
      'model': 'res.partner',
      'method': 'search_read',
      'args': [],
      'kwargs': {
        'context': {'bin_size': true},
        'domain': [],
        'fields': ['id', 'name', 'email', '__last_update', 'image_128'],
        'limit': 80,
      },
    });
  }

  Widget buildListItem(Map<String, dynamic> record) {
    var unique = record['__last_update'] as String;
    unique = unique.replaceAll(RegExp(r'[^0-9]'), '');
    final avatarUrl =
        '${orpc.baseURL}/web/image?model=res.partner&field=image_128&id=${record["id"]}&unique=$unique';
    return ListTile(
      leading: CircleAvatar(backgroundImage: NetworkImage(avatarUrl)),
      title: Text(record['name']),
      subtitle: Text(record['email'] is String ? record['email'] : ''),
    );
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Contacts'),
      ),
      body: Center(
        child: FutureBuilder(
            future: fetchContacts(),
            builder: (BuildContext context, AsyncSnapshot<dynamic> snapshot) {
              if (snapshot.hasData) {
                return ListView.builder(
                    itemCount: snapshot.data.length,
                    itemBuilder: (context, index) {
                      final record = snapshot.data[index] as Map<String, dynamic>;
                      return buildListItem(record);
                    });
              } else {
                if (snapshot.hasError) return Text('Unable to fetch data');
                return CircularProgressIndicator();
              }
            }),
      ),
    );
  }
}

更多关于Flutter远程过程调用插件kangaroo_rpc的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter远程过程调用插件kangaroo_rpc的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


kangaroo_rpc 是一个用于 Flutter 的远程过程调用(RPC)插件,它允许你在 Flutter 应用中与远程服务器进行通信。使用 kangaroo_rpc,你可以轻松地调用远程服务器上的方法,并处理返回的数据。

安装

首先,你需要在 pubspec.yaml 文件中添加 kangaroo_rpc 依赖:

dependencies:
  flutter:
    sdk: flutter
  kangaroo_rpc: ^1.0.0  # 请使用最新版本

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

基本用法

  1. 导入包

    在你的 Dart 文件中导入 kangaroo_rpc

    import 'package:kangaroo_rpc/kangaroo_rpc.dart';
    
  2. 创建 RPC 客户端

    你需要创建一个 RpcClient 实例来与服务器通信:

    final rpcClient = RpcClient(
      baseUrl: 'https://your-server-url.com',  // 替换为你的服务器地址
      headers: {
        'Authorization': 'Bearer your-token',  // 如果需要授权
      },
    );
    
  3. 调用远程方法

    使用 call 方法来调用远程服务器上的方法:

    final response = await rpcClient.call(
      method: 'yourMethodName',  // 远程方法名
      params: {
        'param1': 'value1',  // 传递的参数
        'param2': 'value2',
      },
    );
    
    if (response.isSuccess) {
      print('Response: ${response.data}');
    } else {
      print('Error: ${response.error}');
    }
    
  4. 处理响应

    call 方法返回一个 RpcResponse 对象,你可以通过 isSuccess 属性来判断调用是否成功,并通过 dataerror 来获取返回的数据或错误信息。

高级用法

  • 自定义请求方法

    你可以通过 httpMethod 参数来指定 HTTP 请求方法(如 GETPOST 等):

    final response = await rpcClient.call(
      method: 'yourMethodName',
      params: {
        'param1': 'value1',
      },
      httpMethod: HttpMethod.post,  // 使用 POST 请求
    );
    
  • 处理异常

    你可以使用 try-catch 块来捕获和处理异常:

    try {
      final response = await rpcClient.call(
        method: 'yourMethodName',
        params: {
          'param1': 'value1',
        },
      );
    
      if (response.isSuccess) {
        print('Response: ${response.data}');
      } else {
        print('Error: ${response.error}');
      }
    } catch (e) {
      print('Exception: $e');
    }
    
  • 自定义超时时间

    你可以通过 timeout 参数来设置请求的超时时间:

    final rpcClient = RpcClient(
      baseUrl: 'https://your-server-url.com',
      timeout: Duration(seconds: 10),  // 设置超时时间为 10 秒
    );
回到顶部