Flutter协议客户端插件proto_base_client的使用

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

Flutter协议客户端插件proto_base_client的使用

标题

ProtoBase Client

内容

ProtoBase Client 是一个简单且轻量级的 Dart 包,旨在帮助开发者轻松地将认证和数据库功能集成到应用中。它提供了通过 ProtoBase API 使用电子邮件或用户名进行注册和登录的方法,以及数据库操作方法。

特性

  • 基于电子邮件的认证

    • 使用电子邮件、密码和用户名注册。
    • 使用电子邮件、密码和用户名登录。
  • 基于用户名的认证

    • 使用用户名和密码注册。
    • 使用用户名和密码登录。
  • API Token 使用

    • 官方网站 获取您的 API 密钥。
    • 使用 API 密钥来验证请求。
  • 数据库操作

    • 创建表。
    • 插入数据到表。
    • 读取表中的数据。
    • 更新表中的数据。
    • 删除表中的数据。

安装

pubspec.yaml 文件中添加以下内容:

dependencies:
  proto_base_client: ^2.1.1-dev

运行 flutter pub get 来安装该包。

使用示例

import 'package:proto_base_client/proto_base_client.dart';

void main() async {
  final client = ProtoBaseApiClient();
  final dbClient = ProtoBaseDatabaseClient();

  // 示例使用:认证
  final signupResponse = await client.signupWithEmail(
    'username',
    'password',
    'email@example.com',
    'api_token',
  );
  print(signupResponse);

  // 示例使用:数据库操作
  final createTableResponse = await dbClient.createTable(
    'api_token',
    'username',
    'project_name',
    'table_name',
    ['column1', 'column2'],
    ['type1', 'type2'],
  );
  print(createTableResponse);
}

API 端点

此包与以下 API 端点交互:

  • /auth_api/email-signup/
  • /auth_api/email-signin/
  • /auth_api/user-signup/
  • /auth_api/user-signin/
  • /db_api/create_table
  • /db_api/insert_data
  • /db_api/read_data
  • /db_api/update_data
  • /db_api/delete_data

许可证

此包遵循 MIT License。 详情请参阅 LICENSE 文件。


示例代码

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

import 'home.dart';

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

class MyApp extends StatefulWidget {
  [@override](/user/override)
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  final ProtoBaseApiClient client = ProtoBaseApiClient();

  final ProtoBaseDatabaseClient _client = ProtoBaseDatabaseClient();

  final String _apiToken = 'Your Token Here';
  // 替换为您的 API 密钥
  final String _username = 'Your_Username';
  // 替换为您的用户名
  final String _projectName = 'Spendit';
  // 替换为您的项目名称
  String _response = '';

  void _createTable() async {
    try {
      final result = await _client.createTable(
        _apiToken,
        _username,
        _projectName,
        'test_table',
        ['id', 'name', 'age'],
        ['int', 'text', 'int'],
      );
      setState(() {
        _response = result.toString();
      });
    } catch (e) {
      setState(() {
        _response = 'Error: $e';
      });
    }
  }

  void _insertData() async {
    try {
      final result = await _client.insertData(
        _apiToken,
        _username,
        _projectName,
        'test_table',
        {'id': 1, 'name': 'John Doe', 'age': 30},
      );
      setState(() {
        _response = result.toString();
      });
    } catch (e) {
      setState(() {
        _response = 'Error: $e';
      });
    }
  }

  void _readData() async {
    try {
      final result = await _client.readData(
        _apiToken,
        _username,
        _projectName,
        'test_table',
      );
      setState(() {
        _response = result.toString();
      });
    } catch (e) {
      setState(() {
        _response = 'Error: $e';
      });
    }
  }

  void _updateData() async {
    try {
      final result = await _client.updateData(
        _apiToken,
        _username,
        _projectName,
        'test_table',
        'id = 1',
        {'name': 'Jane Doe', 'age': 25},
      );
      setState(() {
        _response = result.toString();
      });
    } catch (e) {
      setState(() {
        _response = 'Error: $e';
      });
    }
  }

  void _deleteData() async {
    try {
      final result = await _client.deleteData(
        _apiToken,
        _username,
        _projectName,
        'test_table',
        'id = 1',
      );
      setState(() {
        _response = result.toString();
      });
    } catch (e) {
      setState(() {
        _response = 'Error: $e';
      });
    }
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'ProtoBase Client Demo',
      home: Scaffold(
        appBar: AppBar(title: Text('ProtoBase Client Demo')),
        body: Center(
          child: Column(
            children: [
              ElevatedButton(
                onPressed: () async {
                  await client.signinWithEmail(
                    'Technoblade',
                    'never',
                    'dies@gmail.com',
                    'UOUuh66m6lv1OeChrtuZQLCY0VyLIv6aniI8mJgNun3y2lmK5DhgOgu98K1Ei33Zhm903FHNfCUv03cQKpJ5BXA',
                    context,
                    HomePage(),
                  );
                },
                child: Text('Sign Up'),
              ),
              
              ElevatedButton(
                onPressed: _createTable,
                child: Text('Create Table'),
              ),
              ElevatedButton(
                onPressed: _insertData,
                child: Text('Insert Data'),
              ),
              ElevatedButton(onPressed: _readData, child: Text('Read Data')),
              ElevatedButton(
                onPressed: _updateData,
                child: Text('Update Data'),
              ),
              ElevatedButton(
                onPressed: _deleteData,
                child: Text('Delete Data'),
              ),
              SizedBox(height: 20),
              Expanded(
                child: SingleChildScrollView(
                  child: Text(_response, style: TextStyle(fontSize: 16)),
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

更多关于Flutter协议客户端插件proto_base_client的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter协议客户端插件proto_base_client的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,以下是一个关于如何在Flutter项目中使用proto_base_client插件的示例代码。这个示例假设你已经有一个定义好的Protocol Buffers(.proto)文件,并且已经生成了相应的Dart代码。

前提条件

  1. 安装proto_base_client插件: 确保你已经将proto_base_client添加到了你的pubspec.yaml文件中。

    dependencies:
      flutter:
        sdk: flutter
      proto_base_client: ^x.y.z  # 请替换为实际的版本号
    
  2. 生成Dart代码: 使用protoc编译器和protoc-gen-dart插件将你的.proto文件转换为Dart代码。

    protoc --dart_out=. path/to/your/file.proto
    

示例代码

假设你有一个简单的.proto文件,如下所示:

syntax = "proto3";

package example;

service ExampleService {
  rpc SayHello (HelloRequest) returns (HelloResponse);
}

message HelloRequest {
  string name = 1;
}

message HelloResponse {
  string message = 1;
}

生成的Dart代码可能如下所示(简化版):

// example.pb.dart

syntax = "proto3";

@ProtoClass()
class HelloRequest extends $pb.GeneratedMessage {
  static final $pb.BuilderInfo _i = $pb.BuilderInfo(const {'1': 'name'}, {
    'name': $pb.PbFieldInfo(1, $pb.PbFieldType.OS, 'name', '')
  });

  HelloRequest() : super();
  HelloRequest.fromBuffer($core.ByteData buffer, {$core.int offset} = {}) : super.fromBuffer(buffer, offset);
  HelloRequest.fromJson($core.Map<$core.String, dynamic> json) : super.fromJson(json);
  HelloRequest clone() => HelloRequest().mergeFromMessage(this);
  HelloRequest mergeFrom($pb.CodedInputStream input, {$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY}) => _i.mergeFrom(input, this, r);
  $core.String getName() => $_getS(0, '');
  set name($core.String v) { $_setString(0, v); }
  $core.bool hasName() => $_has(0);
  void clearName() => clearField(1);
}

@ProtoClass()
class HelloResponse extends $pb.GeneratedMessage {
  static final $pb.BuilderInfo _i = $pb.BuilderInfo(const {'1': 'message'}, {
    'message': $pb.PbFieldInfo(1, $pb.PbFieldType.OS, 'message', '')
  });

  HelloResponse() : super();
  HelloResponse.fromBuffer($core.ByteData buffer, {$core.int offset} = {}) : super.fromBuffer(buffer, offset);
  HelloResponse.fromJson($core.Map<$core.String, dynamic> json) : super.fromJson(json);
  HelloResponse clone() => HelloResponse().mergeFromMessage(this);
  HelloResponse mergeFrom($pb.CodedInputStream input, {$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY}) => _i.mergeFrom(input, this, r);
  $core.String getMessage() => $_getS(0, '');
  set message($core.String v) { $_setString(0, v); }
  $core.bool hasMessage() => $_has(0);
  void clearMessage() => clearField(1);
}

class ExampleServiceClient extends $grpc.Client {
  static final $grpc.ServiceDescription serviceDescription = $grpc.ServiceDescription(
    'ExampleService',
    'example.ExampleService',
    [
     $grpc.MethodDescriptor<HelloRequest, HelloResponse>(
       'SayHello',
       '/example.ExampleService/SayHello',
       $grpc.PbCodec.forMessage(HelloRequest),
       $grpc.PbCodec.forMessage(HelloResponse),
       $core.List<$core.int>(),
       $core.List<$core.int>()
     )
    ],
    {}
  );

  ExampleServiceClient(Channel channel, {$grpc.CallOptions? options}) : super(channel, options);
  $grpc.ResponseFuture<HelloResponse> sayHello(HelloRequest request, {$grpc.CallOptions? options}) {
    return $createUnaryCall(_$sayHello, request, options);
  }
  function _$sayHello($grpc.ServiceCall call, $core.Map<$core.int, $core.List<$core.int>> requestHeaders) {
    $core.Map<$core.int, $core.List<$core.int>> responseHeaders = {};
    return $grpc.Channel.call(
      call,
      requestHeaders,
      serviceDescription.sayHello,
      $grpc.PbCodec.forMessage(HelloRequest),
      $grpc.PbCodec.forMessage(HelloResponse),
      null,
      responseHeaders
    );
  }
}

使用proto_base_client进行RPC调用

在你的Flutter项目中,你可以像这样使用生成的客户端代码:

import 'package:flutter/material.dart';
import 'package:grpc/grpc-web.dart';
import 'package:proto_base_client/proto_base_client.dart'; // 假设这是你的插件包名
import 'example.pb.dart'; // 导入生成的ProtoBuf Dart文件

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Flutter gRPC Client'),
        ),
        body: Center(
          child: RpcClientDemo(),
        ),
      ),
    );
  }
}

class RpcClientDemo extends StatefulWidget {
  @override
  _RpcClientDemoState createState() => _RpcClientDemoState();
}

class _RpcClientDemoState extends State<RpcClientDemo> {
  String? responseMessage;

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

  void _makeRpcCall() async {
    // 假设你的grpc服务器在https://your-grpc-server-url
    final channel = GrpcWebClientChannel.forAddress('https://your-grpc-server-url',
      options: GrpcWebChannelOptions(
        transport: GrpcWebTransportType.HTTP_2,
      ),
    );

    final stub = ExampleServiceClient(channel);

    final request = HelloRequest()..name = 'World';
    try {
      final response = await stub.sayHello(request);
      setState(() {
        responseMessage = response.message;
      });
    } catch (e) {
      print('RPC call failed: $e');
    }
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      mainAxisAlignment: MainAxisAlignment.center,
      children: <Widget>[
        Text('Hello, gRPC!'),
        if (responseMessage != null)
          Text('Response: $responseMessage'),
      ],
    );
  }
}

在这个示例中,我们创建了一个简单的Flutter应用,它在启动时向gRPC服务器发送一个RPC请求,并显示服务器的响应。请确保将https://your-grpc-server-url替换为你的实际gRPC服务器URL。

回到顶部