Flutter数据传输插件conduit的使用

Flutter数据传输插件conduit的使用

简介

Conduit 是一个现代的 Dart HTTP 服务器框架,它是 Stablekernel 的 Aqueduct 的分支。Conduit 提供了丰富的功能,包括 ORM、OAuth2 认证等,非常适合用于构建后端服务。

安装和配置

安装 Dart

首先,确保你已经安装了 Dart。你可以从 Dart 官方网站 获取安装指南。

激活 Conduit

dart pub global activate conduit

创建项目

conduit create my_project

启动项目

cd my_project
conduit serve

示例代码

以下是一个简单的示例,展示了如何使用 Conduit 构建一个包含 ORM 和 OAuth2 认证的 HTTP 应用程序。

项目结构

假设你的项目结构如下:

my_project/
├── config.yaml
├── lib/
│   └── app.dart
├── web/
│   └── main.dart
└── pubspec.yaml

配置文件 config.yaml

database:
  username: your_username
  password: your_password
  host: localhost
  port: 5432
  databaseName: your_database

主应用程序 lib/app.dart

import 'dart:async';
import 'dart:io';
import 'package:conduit_core/conduit_core.dart';
import 'package:conduit_core/managed_auth.dart';
import 'package:conduit_postgresql/conduit_postgresql.dart';

Future main() async {
  final app = Application<App>()
    ..options.configurationFilePath = 'config.yaml'
    ..options.port = 8888;

  await app.start(numberOfInstances: 3);
}

class App extends ApplicationChannel {
  late ManagedContext context;
  late final AuthServer authServer;

  @override
  Future prepare() async {
    final config = AppConfiguration.fromFile(File(options!.configurationFilePath!));
    final db = config.database;
    final persistentStore = PostgreSQLPersistentStore.fromConnectionInfo(
      db.username,
      db.password,
      db.host,
      db.port,
      db.databaseName,
    );
    context = ManagedContext(
      ManagedDataModel.fromCurrentMirrorSystem(),
      persistentStore,
    );

    authServer = AuthServer(ManagedAuthDelegate(context));
  }

  @override
  Controller get entryPoint {
    return Router()
      ..route('/auth/token').link(() => AuthController(authServer))
      ..route('/users/[:id]')
          .link(() => Authorizer(authServer))!
          .link(() => UserController(context, authServer));
  }
}

class UserController extends ResourceController {
  UserController(this.context, this.authServer);

  final ManagedContext? context;
  final AuthServer authServer;

  @Operation.get()
  Future<Response> getUsers() async {
    final query = Query<User>(context!);
    return Response.ok(await query.fetch());
  }

  @Operation.get('id')
  Future<Response> getUserById(@Bind.path('id') int id) async {
    final q = Query<User>(context!)..where((o) => o.id).equalTo(id);
    final user = await q.fetchOne();

    if (user == null) {
      return Response.notFound();
    }

    return Response.ok(user);
  }

  @Operation.post()
  Future<Response> createUser(@Bind.body() User user) async {
    if (user.username == null || user.password == null) {
      return Response.badRequest(
        body: {"error": "username and password required."},
      );
    }

    final salt = generateRandomSalt();
    final hashedPassword = authServer.hashPassword(user.password!, salt);

    final query = Query<User>(context!)
      ..values = user
      ..values.hashedPassword = hashedPassword
      ..values.salt = salt
      ..values.email = user.username;

    final u = await query.insert();
    final token = await authServer.authenticate(
      u.username,
      query.values.password,
      request!.authorization!.credentials!.username,
      request!.authorization!.credentials!.password,
    );

    return AuthController.tokenResponse(token);
  }
}

class AppConfiguration extends Configuration {
  AppConfiguration.fromFile(super.file) : super.fromFile();

  late DatabaseConfiguration database;
}

class User extends ManagedObject<_User> implements _User, ManagedAuthResourceOwner<_User> {
  @Serialize(input: true, output: false)
  String? password;
}

class _User extends ResourceOwnerTableDefinition {
  @Column(unique: true)
  String? email;
}

运行项目

  1. 确保你的 PostgreSQL 数据库已经启动并运行。
  2. 在项目根目录下运行以下命令启动服务器:
conduit serve

总结

通过以上步骤,你已经成功创建了一个使用 Conduit 构建的 HTTP 服务器,并且集成了 ORM 和 OAuth2 认证。你可以根据需要扩展和修改这个示例,以满足你的具体需求。更多文档和示例可以参考 Conduit 官方文档


更多关于Flutter数据传输插件conduit的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

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


当然,以下是一个关于如何在Flutter项目中使用conduit插件进行数据传输的示例代码。conduit是一个用于Flutter和Dart的数据传输插件,它允许在Flutter应用中轻松地进行跨平台的数据通信。

首先,确保你已经在你的pubspec.yaml文件中添加了conduit依赖:

dependencies:
  flutter:
    sdk: flutter
  conduit: ^x.y.z  # 替换为最新的版本号

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

接下来,我们将展示如何使用conduit在Flutter中进行基本的数据传输。假设我们有一个简单的场景,其中我们需要从Dart VM(可能是一个后台任务)向Flutter UI发送数据。

Dart VM端代码(Background Task)

创建一个Dart文件,例如background_task.dart,用于模拟后台任务:

import 'package:conduit/conduit.dart';

void main() async {
  // 创建一个Conduit实例
  final conduit = Conduit();

  // 模拟后台任务,发送数据到Flutter UI
  Timer.periodic(Duration(seconds: 1), (timer) async {
    String data = "Hello from Dart VM at ${DateTime.now()}";
    await conduit.send(data);
  });
}

Flutter UI端代码

在你的Flutter项目中,你需要接收从Dart VM发送的数据。你可以在MainActivity.kt(对于Android)或AppDelegate.swift(对于iOS)中配置Conduit的接收端,并将其数据传递到Flutter UI。

Android配置(MainActivity.kt)

package com.example.yourapp

import android.os.Bundle
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.MethodChannel
import io.flutter.plugins.GeneratedPluginRegistrant
import package:conduit/conduit_android.ConduitReceiver

class MainActivity: FlutterActivity() {
    private val CHANNEL = "com.example.yourapp/conduit_channel"

    override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
        super.configureFlutterEngine(flutterEngine)
        GeneratedPluginRegistrant.registerWith(flutterEngine)

        MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL).setMethodCallHandler { call, result ->
            // 这个handler通常用于从Flutter UI向原生发送消息
            // 在这里我们用它来初始化ConduitReceiver
            if (call.method == "initializeConduit") {
                ConduitReceiver.initialize(flutterEngine.dartExecutor.binaryMessenger)
                result.success(null)
            } else {
                result.notImplemented()
            }
        }
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        // 在应用启动时初始化ConduitReceiver
        ConduitReceiver.initialize(flutterEngine!!.dartExecutor.binaryMessenger)

        // 设置接收数据时的回调
        ConduitReceiver.setReceiveListener { data ->
            // 将数据发送到Flutter UI
            val channel = MethodChannel(flutterEngine!!.dartExecutor.binaryMessenger, CHANNEL)
            channel.invokeMethod("receiveData", data)
        }
    }
}

iOS配置(AppDelegate.swift)

import UIKit
import Flutter
import conduit_ios  // 确保你已经通过CocoaPods安装了conduit_ios

@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
  override func application(
    _ application: UIApplication,
    didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
  ) -> Bool {
    GeneratedPluginRegistrant.register(with: self)
    
    // 初始化ConduitReceiver
    let conduitReceiver = ConduitReceiver()
    conduitReceiver.initialize(with: window?.rootViewController as! FlutterViewController)
    
    // 设置接收数据时的回调
    conduitReceiver.setReceiveListener { data in
      // 将数据发送到Flutter UI
      let channel = FlutterMethodChannel(name: "com.example.yourapp/conduit_channel", binaryMessenger: self.binaryMessenger!)
      channel.invokeMethod("receiveData", arguments: data)
    }
    
    return super.application(application, didFinishLaunchingWithOptions: launchOptions)
  }
}

Flutter UI代码(main.dart)

import 'package:flutter/material.dart';
import 'package:conduit/conduit.dart';
import 'dart:ui' as ui;

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

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

class _MyAppState extends State<MyApp> {
  String receivedData = "";

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

    // 初始化Conduit并设置接收数据的回调
    Conduit.instance.initialize().then((_) {
      Conduit.instance.receiveStream.listen((data) {
        setState(() {
          receivedData = data;
        });
      });
    });

    // 通知原生端初始化Conduit(对于Android和iOS可能需要)
    if (Platform.isAndroid || Platform.isIOS) {
      ui.window.defaultRouteName = "/initializeConduit";
    }
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Conduit Demo'),
        ),
        body: Center(
          child: Text('Received Data: $receivedData'),
        ),
      ),
    );
  }
}

在这个示例中,Dart VM端的background_task.dart定期发送数据到Flutter UI。Flutter UI通过Conduit插件接收这些数据,并在UI中显示。对于Android和iOS,我们分别在MainActivity.ktAppDelegate.swift中设置了接收数据的回调,并将数据通过MethodChannel发送到Flutter UI。

请注意,这只是一个基本示例,实际应用中可能需要更多的错误处理和配置。希望这个示例能帮你理解如何在Flutter项目中使用conduit插件进行数据传输。

回到顶部