Rust + Flutter for Mobile Applications


As next week will have importat launch for Rust 2018 and Flutter 1.0, I thought to build an app using Rust for the business logic and Flutter for the user interface, that can run at both Android and iOS, I built one and tested it at Android and it is working fine.

I just wonder how to measure the performance and compare it with native Android/iOS app.

The app flow is:

  1. Main is in Flutter, that is calling native function through platform_channel
  2. The native function is calling rust library through JNI (JNI wrapper is required to be call the rust library)

The structure is as below:

The code used is:


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

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

class MyApp extends StatelessWidget {
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
      home: MyHomePage(title: 'Flutter Demo Home Page'),

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

  final String title;

  _MyHomePageState createState() => _MyHomePageState();

class _MyHomePageState extends State<MyHomePage> {
  static const platform = const MethodChannel('');

  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;

  Widget build(BuildContext context) {
    return Material(
      child: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.spaceEvenly,
          children: [
              child: Text('Get Battery Level'),
              onPressed: _getBatteryLevel,

JNI wrapper - RustGreetings.kt

package com.mozilla.greetings

class RustGreetings {
    companion object {
        init {

    private external fun greeting(pattern: String): String

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

And the Main Android activity is:

package com.example.batterylevel

import android.os.Bundle
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 = ""

  override fun onCreate(savedInstanceState: Bundle?) {

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

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


  private fun getBatteryLevel(): Int {
    val batteryLevel: Int
      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

In the Android I just added the below, as I’m interested to check also the impact of adding kotlin JVM library and getting it interacted with the Rust library within the mobile application:

dependencies {

My question is:
How can check the performance and impact of each process when it is executed or called by another process


A good question.

I would probably write a function that does effectively nothing, in Rust and in Dart, run it 1000 times and compare the result,

A function can be “add one to a number”, and a test would be just calling this function 10000 times from Dart and measuring total time. This should give a lower bound on Dart->JNI->Native overhead.

One need to make sure though that the Dart’s version really calles a function, and not just inlines and constant folds it. One way to do that would be to force a dynamic dispatch when calling a function.


You might be interesting in this dart issue:

I am personally extremely excited about Rust/Flutter combo, I think it could be both the most advanced and versitale GUI toolkit and a quick hack to get production ready GUI for free.

However, Dart does not have direct C ffi now, only via Java/Objective-C layer, which means a huge drop in performance and a huge increase in accidental complexity.

That issue is about native ffi capabilities to Dart.