Flutter学习-项目创建

谢典
2023-12-01

Flutter 部分

创建Flutter Module

  • 使用Android Studio 直接创建

生成 aar 和 framework

  • 编译脚本如下

version=1.2
flutter build aar --build-number=$version
flutter build ios-framework

Flutter中 代码

  • main.dart
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_a/second.dart';

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

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
      //定义 flutter中的路由
      routes: {"flutter_a/second": (context) => SecondPage()},
    );
  }
}

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

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

class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;
  String _back = "";
  //创建 showToast的Method Channel 进行和Android端通信
  MethodChannel methodChannel = MethodChannel("com.flutter_a.showToast");

  @override
  void initState() {
    super.initState();
    
    //监听 Android发送的信息
    methodChannel.setMethodCallHandler((call) => _setBack(call));
  }

  void _incrementCounter() {
    setState(() {
      _counter++;
    });
  }

  Future<dynamic> _setBack(MethodCall call) {
    print("${call.method}::${call.arguments}");
    setState(() {
      _back = call.arguments;
    });
    return Future.delayed(Duration(seconds: 1));
  }

  void _sendToNative(
    String msg,
  ) {
    methodChannel.invokeMethod("showToast", {"msg": msg});
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(_back),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              '$_counter',
              style: Theme.of(context).textTheme.headline4,
            ),
            IconButton(
                icon: Icon(Icons.send),
                onPressed: () {
                  _sendToNative("msg:$_counter");
                }),
            MaterialButton(
              onPressed: () {
                Navigator.of(context)
                    .push(MaterialPageRoute(builder: (context) {
                  return SecondPage();
                }));
              },
              child: Center(
                child: Row(
                  children: [Text("next"), Icon(Icons.skip_next)],
                ),
              ),
            )
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: Icon(Icons.add),
      ), 
    );
  }
}

  • second.dart
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';

class SecondPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("second"),
      ),
      body: Center(
        child: Text("second page"),
      ),
    );
  }
}

Android 部分

在 Android 中引入 生成的aar

  • 在app/build.gradle中 加入
repositories {
    String storageUrl = System.env.FLUTTER_STORAGE_BASE_URL ?: "https://storage.googleapis.com"

    maven {
        url '换成自己的Flutter module的路径/flutter_modules/flutter_a/build/host/outputs/repo'
    }
    maven {
        url "$storageUrl/download.flutter.io"
    }
}
dependencies{
    ....
    debugImplementation 'com.example.flutter_a:flutter_debug:1.0'
    releaseImplementation 'com.example.flutter_a:flutter_release:1.0'
}

使用 FlutterEngineCache 缩减 启动Flutter 界面的黑屏时间

  • 在自定义的Application中 创建FlutterEngine

package com.example.fluttertest2

import android.app.Application
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.embedding.engine.FlutterEngineCache
import io.flutter.embedding.engine.dart.DartExecutor

class MyApplication : Application() {
    companion object {
        const val CACHE_MAIN = "main"
        const val CACHE_SECOND = "second"
        const val CACHE_ID = "CACHE_ID"
    }

    override fun onCreate() {
        super.onCreate()
        val flutterEngine = FlutterEngine(this)
        flutterEngine.dartExecutor.executeDartEntrypoint(DartExecutor.DartEntrypoint.createDefault())
        FlutterEngineCache.getInstance().put(CACHE_MAIN, flutterEngine)

        val second = FlutterEngine(this)
        // 设置 Flutter的初始化路由,不设置则使用 默认的路由 
        second.navigationChannel.setInitialRoute("flutter_a/second")
        second.dartExecutor.executeDartEntrypoint(DartExecutor.DartEntrypoint.createDefault())
        FlutterEngineCache.getInstance().put(CACHE_SECOND, second)
    }
}

flutter_a/second 是在 main.dart 中“routes”定义的

  • 在 自定义的FlutterActivity中获取缓存的FlutterEngine
package com.example.fluttertest2

import com.example.fluttertest2.MyApplication.Companion.CACHE_SECOND
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugins.GeneratedPluginRegistrant

class SecondFlutterActivity : FlutterActivity() {
    override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
        super.configureFlutterEngine(flutterEngine)
        GeneratedPluginRegistrant.registerWith(flutterEngine)
    }

    override fun getCachedEngineId(): String? {
        //FlutterEngineCache 中 FlutterEngine的key
        return CACHE_SECOND
    }
}
  • Android原生Activity跳转到flutter界面的方式
package com.example.fluttertest2

import android.content.Intent
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import com.example.fluttertest2.MyApplication.Companion.CACHE_ID
import com.example.fluttertest2.MyApplication.Companion.CACHE_MAIN
import com.example.fluttertest2.MyApplication.Companion.CACHE_SECOND
import kotlinx.android.synthetic.main.activity_main.*

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        goFlutter.setOnClickListener {
            //将 FlutterEngineCache 中 FlutterEngine的 key 传递到 FlutterActivity,根据key加载不同的FlutterEngine的
            startActivity(Intent(this, MyFlutterActivity::class.java).putExtra(CACHE_ID,CACHE_MAIN))
        }

        goSecond.setOnClickListener {
            //打开新的FlutterActivity
            startActivity(Intent(this, SecondFlutterActivity::class.java))

            //使用一个FlutterActivity
//            startActivity(Intent(this, MyFlutterActivity::class.java).putExtra(CACHE_ID,CACHE_SECOND))

        }
    }
}

  • MyFlutterActivity
import com.example.fluttertest2.MyApplication.Companion.CACHE_ID
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugins.GeneratedPluginRegistrant

class MyFlutterActivity : FlutterActivity() {

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

    override fun getCachedEngineId(): String? {
//        return CACHE_MAIN
        return intent.getStringExtra(CACHE_ID)
    }
}

MethodChannel 通信

  • Android端在configureFlutterEngine 方法中创建MethodChannel对象:
import android.widget.Toast
import com.example.fluttertest2.MyApplication.Companion.CACHE_ID
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.MethodChannel
import io.flutter.plugins.GeneratedPluginRegistrant

class MyFlutterActivity : FlutterActivity() {

    override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
        super.configureFlutterEngine(flutterEngine)
        GeneratedPluginRegistrant.registerWith(flutterEngine)
        val methodChannel = MethodChannel(flutterEngine.dartExecutor.binaryMessenger, "com.flutter_a.showToast")
    
       //监听 flutter发送的信息
        methodChannel.setMethodCallHandler { call, result ->
            result.success("back from native")
            Toast.makeText(
                this@MyFlutterActivity,
                "from Flutter:${call.argument<String>("msg")}",
                Toast.LENGTH_SHORT
            ).show()
        }
        
        //调用 Flutter 中的方法 
        methodChannel.invokeMethod("sayHi", "hello Flutter", object : MethodChannel.Result {
            override fun notImplemented() {}
            override fun error(errorCode: String?, errorMessage: String?, errorDetails: Any?) {}
            override fun success(result: Any?) {}
        })
    }

    override fun getCachedEngineId(): String? {
//        return CACHE_MAIN
        return intent.getStringExtra(CACHE_ID)
    }

}

IOS部分

  • 正在学习中。。。
 类似资料: