Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Flutter + Go で 組み合わせた モバイルアプリ開発

Flutter + Go で 組み合わせた モバイルアプリ開発

Go Conference 2021 Springで発表した内容です。
https://gocon.jp/sessions/session-a11-s/

# 関連リンク

gomobile について
https://github.com/golang/go/wiki/Mobile

サンプルアプリ
https://github.com/glassmonkey/flutter_with_golang

govaluate (サンプルアプリで使用したライブラリ)
https://github.com/Knetic/govaluate

# 参考記事
Go MobileてAndroidアプリを開発
https://www.slideshare.net/takuyaueda967/go-mobileandroid

Using Go Library in Flutter
https://medium.com/flutter-community/using-go-library-in-flutter-a04e3496aa05

アプリ開発にgomobileを利用する(Android/iOS/Flutter)
https://qiita.com/kabochapo/items/b37c03ea9d30572fbd59

ネイティブから逃げるな。Pigeonを使ったタイプセーフなFlutter + ネイティブ開発
https://qiita.com/glassmonkey/items/51d150da15ceeaea2960

glassmonenkey

April 27, 2021
Tweet

More Decks by glassmonenkey

Other Decks in Technology

Transcript

  1. 1 © 2012-2021 BASE, Inc. Flutter + Go で 組み合わせた

    モバイルアプリ開発  永野 峻輔(@glassmonekey) Go Conference2021 Spring
  2. 2 © 2012-2021 BASE, Inc. 自己紹介 所属 BASE BANK株式会社 Software

    Developer Go, PHP, Pythonあたりをよく書いています Go Conference 初参加です。 趣味 Flutterアプリ開発の勉強 締め切りに追われること アニメ鑑賞 / ウマ娘 SNS Twitter: @glassmonekey  Github: https://github.com/glassmonkey (永野 なので エターナルフィールドです) 永野 峻輔 (ながの しゅんすけ)
  3. 3 © 2012-2021 BASE, Inc. Today’s topic • Why Flutter

    + gomobile ? • What is Flutter ? • What is gomobile ? • Try Flutter + gomobile • Conclustion
  4. 5 © 2012-2021 BASE, Inc. Why Flutter + gomobile ?

    • I want to reduce the difference between IOS and Android. • I want to use the Go library when developing Flutter mobile app. • Both Go and Flutter have wonderful development experience.
  5. 8 © 2012-2021 BASE, Inc. What is Flutter ? Flutter

    is Google’s UI toolkit for building beautiful, natively compiled applications for mobile, web, and desktop from a single codebase. https://flutter.dev/
  6. 9 © 2012-2021 BASE, Inc. Flutter features • Hot reload

    !!!!!! • Declarative • Multi Platform (Android, iOS, Web etc…) https://flutter.dev/docs/resources/architectural-overview
  7. 12 © 2012-2021 BASE, Inc. Why Flutter Uses Dart? https://hackernoon.com/why-flutter-uses-dart-dd635a054ebf

    2 ways compile ◦ AOT (Ahead of time) ◦ JIT (Just in time) Ecosystems ◦ pub.dev (Plugin Repository ) ◦ dart.pad (play ground) ◦ etc….
  8. 14 © 2012-2021 BASE, Inc. Flutter + Native + Go(mobile)

    https://flutter.dev/docs/development/platform-integration/platform-channels Objective-C gomobile (SDK)
  9. 16 © 2012-2021 BASE, Inc. What is gomobile https://github.com/golang/mobile Tools

    to build mobile applications. • Writing all-Go native mobile applications. • Writing SDK applications by generating bindings from a Go package and invoke them from Java (on Android) and Objective-C (on iOS).
  10. 17 © 2012-2021 BASE, Inc. How to use gomobile https://github.com/golang/go/wiki/Mobile

    Go 1.15.8~ 😇 (cgo bug fixed) Android NDK, Android studio (Flutter / Android) Xcode (iOS) conditions $ go get golang.org/x/mobile/cmd/gomobile $ gomobile init
  11. 20 © 2012-2021 BASE, Inc. native applications https://github.com/golang/go/wiki/Mobile l $

    go get -d golang.org/x/mobile/example/basic $ gomobile build -target=android \ golang.org/x/mobile/example/basic $ gomobile build -target=ios \ golang.org/x/mobile/example/basic Current version is not working 😇 Build for Android Initialize for Sample Application Build for iOS
  12. 25 © 2012-2021 BASE, Inc. Example code (Go) package example

    type Result struct { Message string } func (r Result) Run() (string, error) { return r.Message, nil }
  13. 26 © 2012-2021 BASE, Inc. For SDK applications https://github.com/golang/go/wiki/Mobile $

    gomobile bind -target ios -o /path/to/file.framework source_dir $ export ANDROID_NDK_HOME=/path/to/ndk_dir $ gomobile bind -target android -o /path/to/file.aar source_dir Build for iOS Build for Android
  14. 27 © 2012-2021 BASE, Inc. Part of Java file package

    example; import ... public final class Result implements Proxy { ...(omitted)... public native string run() throws Exception public boolean equals(Object var1) {...} public int hashCode() {...} public String toString() {...} ...(omitted)... } func (r Result) Run() (string, error) { return r.Message, nil } Java Go
  15. 28 © 2012-2021 BASE, Inc. Part of Objective-C file …

    omit …. @class ExampleResult; @interface ExampleResult : NSObject <goSeqRefInterface> { } @property(strong, readonly) _Nonnull id _ref; … omit …. @property (nonatomic) NSString* _Nonnull message; - (NSString* _Nonnull)run:(NSError* _Nullable* _Nullable)error; @end #endif func (r Result) Run() (string, error) { return r.Message, nil } Objective-C Go
  16. 29 © 2012-2021 BASE, Inc. Available types https://pkg.go.dev/golang.org/x/mobile/cmd/gobind - Signed

    integer and floating point types. - String and boolean types. - Byte slice types. Note that byte slices are passed by reference, and support mutation. - Any function type all of whose parameters and results have supported types. Functions must return either no results, one result, or two results where the type of the second is the built-in 'error' type. - Any interface type, all of whose exported methods have supported function types. - Any struct type, all of whose exported methods have supported function types and all of whose exported fields have supported types.
  17. 30 © 2012-2021 BASE, Inc. In Other Words … We

    can’t use Slices and Map 🥺🥺🥺…
  18. 35 © 2012-2021 BASE, Inc. Use External LIbrary example expression,

    err := govaluate.NewEvaluableExpression("10 > 0"); result, err := expression.Evaluate(nil); // result is now set to "true", the bool value https://github.com/Knetic/govaluate Provides support for evaluating arbitrary C-like artithmetic/string expressions. govaluate
  19. 36 © 2012-2021 BASE, Inc. Development Flow • Flutter setting

    • Flutter + Native ◦ Android ◦ iOS • gomobile setting • gomobile + Native ◦ Android ◦ iOS I'll spare you the details of Flutter this time 🙏
  20. 38 © 2012-2021 BASE, Inc. Flutter Project initilize $ flutter

    create ${PROJECT_NAME} $ mkdir -p ${PROJECT_NAME}/golang // Root Directory for Go 2. Create Flutter new project 1. Pass Flutter doctor $ flutter doctor [✓] Flutter (Channel stable, 2.0.4, on Mac OS X 10.15.7 19H524 darwin-x64, locale ja-JP) [✓] Android toolchain - develop for Android devices (Android SDK version 29.0.2) [✓] Xcode - develop for iOS and macOS [✓] Android Studio (version 4.0) Android NDK: 22.0.7026061 version 12.4 (12D4e)
  21. 40 © 2012-2021 BASE, Inc. Pigeon ネイティブから逃げるな。Pigeonを使ったタイプセーフな Flutter + ネイティブ開発

    https://qiita.com/glassmonkey/items/51d150da15ceeae a2960 Pigeon is a code generator tool to make communication between Flutter and the host platform type-safe and easier.
 For details https://pub.dev/packages/pigeon
  22. 41 © 2012-2021 BASE, Inc. Flutter Code evaluation(String text) async

    { final req = Request(); req.expression = text; final response = await this.client.eval(req); this.state = this.state.copyWith(text: response.message ?? "result"); } import 'package:pigeon/pigeon.dart'; class Request { late String expression; } class Response { late String message; } @HostApi() abstract class Api { Response eval(Request req); } iOS or Android Application Code Scheme for Pigeon
  23. 43 © 2012-2021 BASE, Inc. Configure Build Settings android {

    … omit … kotlinOptions { jvmTarget = '1.8' } … omit ... 2. Sync project gradle (Android studio) 1. edit app/build.gradle Pigeon uses calling to static methods in Java interfaces prohibited in JVM target 1.6.
  24. 44 © 2012-2021 BASE, Inc. Native Code (Kotlin) package nagano.shunsuke.flutter_with_golang

    import nagano.shunsuke.plugins.Pigeon class Api() : Pigeon.Api { override fun eval(arg: Pigeon.Request): Pigeon.Response { val response = Pigeon.Response() response.message = "fake"; // fake response return response } } Api.kt @HostApi() abstract class Api { Response eval(Request req); } Kotlin Flutter
  25. 45 © 2012-2021 BASE, Inc. Native Code (Kotlin) package nagano.shunsuke.flutter_with_golang

    import androidx.annotation.NonNull import io.flutter.embedding.android.FlutterActivity import io.flutter.embedding.engine.FlutterEngine import nagano.shunsuke.plugins.Pigeon class MainActivity: FlutterActivity() { override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) { super.configureFlutterEngine(flutterEngine) Pigeon.Api.setup(flutterEngine.dartExecutor.binaryMessenger, Api()) } } MainActivety.kt
  26. 47 © 2012-2021 BASE, Inc. Configure Build Settings 2. To

    be callable from swift 1. Add Pigeon files to Runner (Xcode) #import "GeneratedPluginRegistrant.h" #import "Pigeon.h" // add Runner-Bridging-Header.h
  27. 48 © 2012-2021 BASE, Inc. Native Code (Swift) import Foundation

    import API class Api: FlutterApi { func eval(_ input: FlutterRequest, error: AutoreleasingUnsafeMutablePointer<FlutterError?>) -> FlutterResponse? { let response = FlutterResponse() response.message = "fake" return response } } api.swift @HostApi() abstract class Api { Response eval(Request req); } Swift Flutter
  28. 49 © 2012-2021 BASE, Inc. Native Code (Swift) import UIKit

    import Flutter @UIApplicationMain @objc class AppDelegate: FlutterAppDelegate { override func application( _ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? ) -> Bool { GeneratedPluginRegistrant.register(with: self) let controller: FlutterViewController = window?.rootViewController as! FlutterViewController FlutterApiSetup(controller.binaryMessenger, Api()) return super.application(application, didFinishLaunchingWithOptions: launchOptions) } }
  29. 52 © 2012-2021 BASE, Inc. Sample Project ├── android ├──

    golang │ ├── go.mod │ ├── go.sum │ └── pkg │ └── api ├── ios └── lib root directory for Go exported package to Native
  30. 53 © 2012-2021 BASE, Inc. Go for gomobile (Part) func

    Evaluate(formula string) (float64, error) { expression, err := govaluate.NewEvaluableExpression(formula) if err != nil { return 0, err } i := make(map[string]interface{}) result, err := expression.Evaluate(i) if err != nil { return 0, err } v, ok := result.(float64) if !ok { return 0, fmt.Error("invalid formula result.”) } return v, nil }
  31. 54 © 2012-2021 BASE, Inc. How to use gomobile https://github.com/golang/go/wiki/Mobile

    Go 1.15.8~ 😇 (cgo bug fixed) Android NDK, Android studio Xcode, etc... conditions $ go get golang.org/x/mobile/cmd/gomobile $ gomobile init
  32. 55 © 2012-2021 BASE, Inc. Build SDK applications $ gomobile

    bind -target ios -o ../ios/API.framework \ github.com/glassmonkey/flutter_with_golang/golang/pkg/api $ export ANDROID_NDK_HOME=/path/to/ndk_dir $ gomobile bind -target android -o ../android/API.aar \ github.com/glassmonkey/flutter_with_golang/golang/pkg/api Build for iOS Build for Android (Required Android NDK)
  33. 57 © 2012-2021 BASE, Inc. Configure Build Settings dependencies {

    implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" implementation (name:'API', ext:'aar') repositories { flatDir { dirs '../' } } 2. Sync project gradle (Android studio) 1. edit app/build.gradle
  34. 58 © 2012-2021 BASE, Inc. Part of Native Code (Kotlin)

    override fun eval(arg: Pigeon.Request): Pigeon.Response { val response = Pigeon.Response() return try { val result = Api.evaluate(arg.expression) response.message = result.toString() response } catch (e: Exception ) { response.message = e.toString() response } } Api.kt @HostApi() abstract class Api { Response eval(Request req); } Flutter func Evaluate(formula string) (float64, error) {...} Go
  35. 60 © 2012-2021 BASE, Inc. Configure Build Settings 1. Build

    Phases > LinkBinary With Libraries 2. Add Files (API.framework)
  36. 61 © 2012-2021 BASE, Inc. Part of Native Code (Swift)

    func eval(_ input: FlutterRequest, error: AutoreleasingUnsafeMutablePointer<FlutterError?>) -> FlutterResponse? { let response = FlutterResponse() var result: Double = 0 var error: NSError? ApiEvaluate(input.expression, &result, &error) if error != nil { response.message = "\(error)" return response } response.message = "\(result)" return response } api.swift @HostApi() abstract class Api { Response eval(Request req); } Flutter func Evaluate(formula string) (float64, error) {...} Go
  37. 64 © 2012-2021 BASE, Inc. Setting 1. Run “Profile” 2.

    Flutter Performance → Open Dev tools
  38. 66 © 2012-2021 BASE, Inc. Performance when rebuild Flutter Flutter

    + Native + gomobile Draw Draw CPU Sampling rate (≒5s) clock_ gettime syscall syscall clock_ gettime I couldn't find any clear differences 🥺
  39. 67 © 2012-2021 BASE, Inc. FileSize (Demo) OS with gomobile

    (Yes, No) release file size Android (apk) Yes 20MB ( 125%) iOS Yes 56MB (103%) Android (apk) No 16.2MB iOS No 54 MB
  40. 69 © 2012-2021 BASE, Inc. Flutter + gomobile Pros👍 •

    It can reduce the difference between IOS and Android. • We can easily use the Go library when developing Flutter mobile app. • Both Go and Flutter have wonderful development experience. Cons👎 • Generated size of Artifacts is bigger. • Language bindings have a performance overhead. ◦ I couldn't find any clear differences 🥺 • The available types are limited.
  41. 74 © 2012-2021 BASE, Inc. https://www.slideshare.net/takuyaueda967/go-mobileandroid https://medium.com/flutter-community/using-go-library- in-flutter-a04e3496aa05 Reference アプリ開発にgomobileを利用する

    (Android/iOS/Flutter) Using Go Library in Flutter Go MobileてAndroidアプリを開発 https://qiita.com/kabochapo/items/b37c03ea9d30572fbd59