为移动应用集成 Rust + Flutter + Kotlin

Posted

技术标签:

【中文标题】为移动应用集成 Rust + Flutter + Kotlin【英文标题】:Integrating Rust + Flutter + Kotlin for Mobile Applications 【发布时间】:2019-05-01 03:48:44 【问题描述】:

由于下周将有重要的 Rust 2018 和 Flutter 1.0 发布,我想构建一个使用 Rust 作为业务逻辑和 Flutter 作为用户界面的应用程序,它可以在 androidios 上运行,我构建了一个并进行了测试它在 Android 上运行良好。

我只是想知道如何衡量性能并将其与原生 Android/iOS 应用程序进行比较。

应用流程是:

    Main在Flutter中,即通过platform_channel调用native函数 native函数通过JNI调用rust库(调用rust库需要JNI封装)

结构如下:

使用的代码是:

main.dart:

import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget 
  @override
  Widget build(BuildContext context) 
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  


class MyHomePage extends StatefulWidget 
  MyHomePage(Key key, this.title) : super(key: key);

  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();


class _MyHomePageState extends State<MyHomePage> 
  static const platform = const MethodChannel('samples.flutter.io/battery');

  String _batteryLevel = 'Unknown battery level.';

  Future<void> _getBatteryLevel() async 
    String batteryLevel;
    try 
      final String hello = await platform.invokeMethod('getText');
      final int result = await platform.invokeMethod('getBatteryLevel');

      batteryLevel = '$hello Battery level at $result %.';
     on PlatformException catch (e) 
      batteryLevel = "Failed to get battery level: '$e.message'.";
    

    setState(() 
      _batteryLevel = batteryLevel;
    );
  

  @override
  Widget build(BuildContext context) 
    return Material(
      child: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.spaceEvenly,
          children: [
            RaisedButton(
              child: Text('Get Battery Level'),
              onPressed: _getBatteryLevel,
            ),
            Text(_batteryLevel),
          ],
        ),
      ),
    );
  

JNI wrapper - RustGreetings.kt

package com.mozilla.greetings

class RustGreetings 
    companion object 
        init 
            System.loadLibrary("greetings")
        
    

    private external fun greeting(pattern: String): String

    fun sayHello(to: String): String = greeting(to)

主要的 Android 活动是:

package com.example.batterylevel

import android.os.Bundle
import io.flutter.app.FlutterActivity
import io.flutter.plugins.GeneratedPluginRegistrant
import io.flutter.plugin.common.MethodChannel

import android.content.Context
import android.content.ContextWrapper
import android.content.Intent
import android.content.IntentFilter
import android.os.BatteryManager
import android.os.Build.VERSION
import android.os.Build.VERSION_CODES

import lib.Library
import com.mozilla.greetings.RustGreetings

class MainActivity: FlutterActivity() 
  private val CHANNEL = "samples.flutter.io/battery"

  override fun onCreate(savedInstanceState: Bundle?) 
    super.onCreate(savedInstanceState)
    GeneratedPluginRegistrant.registerWith(this)

    MethodChannel(flutterView, CHANNEL).setMethodCallHandler  call, result ->
      if (call.method == "getText") 
        result.success(getText())
       else if (call.method == "getBatteryLevel") 
       // result.success(getText())
        val batteryLevel = getBatteryLevel()

        if (batteryLevel != -1) 
          result.success(batteryLevel)
         else 
          result.error("UNAVAILABLE", "Battery level not available.", null)
        
      
      else 

        result.notImplemented()
      
    
  

  private fun getBatteryLevel(): Int 
    val batteryLevel: Int
    if (VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP) 
      val batteryManager = getSystemService(Context.BATTERY_SERVICE) as BatteryManager
      batteryLevel = batteryManager.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY)
     else 
      val intent = ContextWrapper(applicationContext).registerReceiver(null, IntentFilter(Intent.ACTION_BATTERY_CHANGED))
      batteryLevel = intent!!.getIntExtra(BatteryManager.EXTRA_LEVEL, -1) * 100 / intent.getIntExtra(BatteryManager.EXTRA_SCALE, -1)
    
    return batteryLevel
  

  private fun getText(): String 
    val x = Library().someLibraryMethod()
    val g = RustGreetings()
    val r = g.sayHello("My $x Rust")
    return r
  

在 Android gradle.build 中,我刚刚添加了以下内容,因为我有兴趣检查添加 kotlin JVM 库并使其与移动应用程序中的 Rust 库交互的影响:

dependencies 
    implementation(files("src/main/libs/lib.jar"))

我的问题是: 如何检查每个进程在被另一个进程执行或调用时的性能和影响

【问题讨论】:

交叉链接到相关的 Rust 用户线程:users.rust-lang.org/t/rust-flutter-for-mobile-applications/… 您将不得不更具体地了解 性能 的含义,但对于一般测试,请参阅 ***.com/a/58772479/6668797,或者对于 ui 性能测试,请参阅flutter.dev/docs/perf/rendering/ui-performance 【参考方案1】:

随着 Dart 中 ffi 的引入,现在事情变得更加顺畅,性能更好,因为现在直接与 Dart/Rust 交互,无需 Dart/Kotlin/Rust 或 Dart/Swift/Rust 循环,下面是一个简单的例子:

第一个src/lib.rs

#[no_mangle]
pub extern fn rust_fn(x: i32) -> i32    
    println!("Hello from rust\nI'll return: ", x.pow(2));
    x.pow(2)
 

Cargo.toml

[package]
name = "Double_in_Rost"
version = "0.1.0"
authors = ["Hasan Yousef"]
edition = "2018"

[lib]
name = "rust_lib"
crate-type = ["dylib"] # could be `staticlib` as well

[dependencies]

运行cargo build --release 将生成target\release\rust_lib.dll 将其复制/粘贴到Dart 应用程序根目录中

如下编写 Dart 代码:

import 'dart:ffi';
import 'dart:io' show Platform;

// FFI signature of the hello_world C function
typedef ffi_func = Int32 Function(Int32 x);  //pub extern fn rust_fn(x: i32) -> i32
// Dart type definition for calling the C foreign function
typedef dart_func = int Function(int x);

void main() 
  // Open the dynamic library
  var path = './rust_lib.so';
  if (Platform.isMacOS) path = './rust_lib.dylib';
  if (Platform.isWindows) path = 'rust_lib.dll';
  final dylib = DynamicLibrary.open(path);
  // Look up the Rust/C function
  final my_func =
      dylib.lookup<NativeFunction<ffi_func>>('rust_fn').asFunction<dart_func>();
  print('Double of 3 is $my_func(3)');

【讨论】:

以上是关于为移动应用集成 Rust + Flutter + Kotlin的主要内容,如果未能解决你的问题,请参考以下文章

如何将 Flutter 移动应用迁移到 Flutter Web

Flutter 小部件与 Flutter 驱动程序

无法分别构建 Flutter Web 和 Flutter Mobile 应用

Flutter能为组织和业务带来多少价值?丨GMTC

谷歌发布Flutter beta 1 :可开发原生APP,支持跨平台

使用Rust为OpenWRT开发应用.