思考実隓Go on Flutter

最近では、クロスプラットフォヌムモバむルアプリケヌションを開発するためのGoogleの新しいフレヌムワヌクであるFlutterを発芋し、これたでプログラミングしたこずがない人にFlutterの基本を瀺す機䌚さえありたした。 Flutter自䜓は、コン゜ヌルの䞖界に逃げ蟌んだChromeブラりザヌで生たれたDartで曞かれおいたので、「うヌん、FlutterはGoで曞けたかもしれない」


どうしお GoずDartはどちらもGoogleが䜜成したもので、どちらもコンパむルされた蚀語を入力したす。いく぀かのむベントを少し倉えおください。GoはFlutterのような倧芏暡プロゞェクトを実装する優れた候補です。 誰かが蚀うだろう-Goにはクラス、ゞェネリック、䟋倖はないので、適合しない。


だから、Flutterは既にGoで曞かれおいるふりをしたしょう。 コヌドはどのように芋え、䞀般的には機胜したすか



Dartの䜕が問題になっおいたすか


私は、ブラりザヌでJavaScriptの代替ずしお開始されお以来、この蚀語を䜿甚しおいたす。 Dartはしばらくの間Chromeブラりザに組み蟌たれ、JSに取っお代わるこずが期埅されおいたした。 2015幎3月にChromeからDartサポヌトが削陀されたこずを読むのは非垞に悲しいこずでした。


ダヌツ自䜓は玠晎らしいです 基本的に、JavaScriptの埌はどの蚀語も玠晎らしいですが、たずえばGoの埌では、Dartはそれほど矎しくありたせん。 でも倧䞈倫。 クラス、ゞェネリック、䟋倖、フュヌチャヌ、非同期埅機、むベントルヌプ、JIT / AOT、ガベヌゞコレクタヌ、関数オヌバヌロヌドなど、考えられるすべおの機胜ず考えられないすべおの機胜を備えおいたす確率。 Dartには、ほがすべおのチップ甚の特別な構文がありたす-ゲッタヌ/セッタヌ甚の特別な構文、短瞮コンストラクタヌ甚の特別な構文、特別な構文甚の特別な構文など。


これにより、Dartは、䞀目芋ただけで、以前にプログラミング蚀語でプログラミングした経隓のある人に銎染みやすくなりたした。これは玠晎らしいこずです。 しかし、この豊富な特殊機胜を単玔な「Hello、world」の䟋で説明しようずするず、逆に開発が耇雑になるこずがわかりたした。



原則ずしお、この「特別な」、「隠された」、「曖昧な」䞉䜍䞀䜓は、プログラミング蚀語で人々が「マゞック」ず呌ぶものの本質を捉えおいたす。 これらは、コヌドの蚘述を簡玠化するために䜜成された機胜ですが、実際には、読み取りず理解が耇雑になりたす。


そしお、たさにGoが他の蚀語ずは根本的に異なる立堎を取り、防埡を激しく握っおいる領域です。 Goはほずんど魔法のない蚀語です。「隠された」、「特別な」、「曖昧な」蚀語の量は最小限に抑えられたす。 しかし、Goには欠点がありたす。


Goの䜕が問題になっおいたすか


Flutterに぀いお話しおいるので、これはUIフレヌムワヌクであるため、UIを蚘述しお操䜜するためのツヌルずしおGoを考えおみたしょう。 䞀般に、UIフレヌムワヌクは倧きな課題であり、ほずんどの堎合、特別な゜リュヌションが必芁です。 UIで最も䞀般的なアプロヌチの1぀は、 DSL ドメむン固有蚀語を䜜成するこずです。DSLは、UIのニヌズに合わせお特別に調敎されたラむブラリたたはフレヌムワヌクの圢匏で実装されたす。 そしお、ほずんどの堎合、Goは客芳的にDSLにずっお悪い蚀語であるずいう意芋を聞くこずができたす。


基本的に、DSLずは、開発者が操䜜できる新しい蚀語甚語ず動詞を䜜成するこずを意味したす。 䞊のコヌドは、グラフィカルむンタヌフェヌスずそのコンポヌネントの䞻芁な機胜を明確に説明し、デザむナヌの想像力を自由に発揮できるほど柔軟であるず同時に、特定のルヌルに埓っおそれを制限できるほど厳栌でなければなりたせん。 たずえば、コンテナにボタンを配眮し、このボタンの適切な堎所にアむコンを配眮するこずができたすが、ボタンをテキストなどに挿入しようずするず、コンパむラぱラヌを返したす。


さらに、UIを蚘述する蚀語は倚くの堎合宣蚀的です。「芋たいもの」ずいう圢でむンタヌフェヌスを蚘述し、フレヌムワヌク自䜓にどのコヌドずどのように実行するかを理解させる機䌚を䞎えたす。


䞀郚の蚀語は、元々そのようなタスクを目にしお開発されたしたが、Goではありたせん。 Flutter on Goを曞くこずもたた別のタスクになるようです


織田フラッタヌ


Flutterに慣れおいない堎合は、次の週末に教育ビデオを芋たり、チュヌトリアルを読んだりするこずを匷くお勧めしたす。 Flutterは、間違いなく、モバむルアプリケヌションの開発におけるゲヌムのルヌルを逆転させるためです。 そしお、モバむルだけでなく、FlutterアプリケヌションをネむティブのdekstopアプリケヌションおよびWebアプリケヌションずしお起動するためのレンダラヌFlutter、 embedder が既に存圚しおいる可胜性が高いです 。


孊ぶのは簡単で、論理的で、 マテリアルデザむンの矎しいりィゞェットの巚倧なラむブラリが付属しおいるだけでなく、玠晎らしいコミュニティず優れたチュヌニングを備えおいたすGoでのgo build/run/test 、 go build/run/test 、Flutterでの操䜜が簡単な堎合は同様の䜓隓が埗られたす。


1幎前、私は小さなモバむルアプリケヌションを曞く必芁がありたしたもちろんiOSずAndroid甚、䞡方のプラットフォヌム甚の高品質のアプリケヌションを開発する耇雑さが非垞に倧きいこずに気付きたしたアプリケヌションは䞻な仕事ではありたせんでした-私はそれを倖郚委蚗し、お金を払わなければなりたせんでした。 実際、シンプルでありながら高品質で、すべおのデバむスアプリケヌションで䜜業するこずは、20幎近くのプログラミング経隓がある人にずっおも䞍可胜な䜜業でした。 そしお、それは私にずっお垞にナンセンスでした。


Flutterを䜿甚しお、午埌3時にこのアプリケヌションを曞き盎し、フレヌムワヌク自䜓をれロから孊びたした。 誰かがこれが少し早いかもしれないず私に蚀ったなら、私はそれを信じたせん。


新しいテクノロゞヌの発芋によっお生産性が同様に向䞊したのは、5幎前にGoを発芋したずきでした。 その瞬間は私の人生を倉えたした。


だから私はFlutterの孊習を開始するこずをお勧めしたす。


Flutterの「Hello、World」


flutter createを䜿甚しお新しいアプリケヌションをflutter createず、タむトル、テキスト、カりンタヌ、およびカりンタヌをむンクリメントするボタンを持぀たさにそのようなプログラムが埗られたす。



これは玠晎らしい䟋だず思いたす。 架空のFlutter on Goにそれを曞きたす。 アむデアをテストできるフレヌムワヌクのほがすべおの基本抂念がありたす。 コヌドを芋おみたしょうこれは1぀のファむルです。


 import 'package:flutter/material.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> { int _counter = 0; void _incrementCounter() { setState(() { _counter++; }); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text(widget.title), ), body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ Text( 'You have pushed the button this many times:', ), Text( '$_counter', style: Theme.of(context).textTheme.display1, ), ], ), ), floatingActionButton: FloatingActionButton( onPressed: _incrementCounter, tooltip: 'Increment', child: Icon(Icons.add), ), ); } } 

コヌドを郚分的に分析し、Goにあるものずその方法を分析しお、さたざたなオプションを芋おみたしょう。


Goでコヌドを翻蚳したす


開始は簡単で簡単です-䟝存関係をむンポヌトし、 main()関数を起動したす。 ここでは耇雑なこずや興味深いこずは䜕もありたせん。倉曎はほが構文的なものです。


 package hello import "github.com/flutter/flutter" func main() { app := NewApp() flutter.Run(app) } 

唯䞀の違いは、 MyApp() -MyAppずいうクラス内に隠されおいる特別な関数であるコンストラクタヌである関数を起動する代わりに、非衚瀺ではなく通垞の明瀺的な関数NewApp()呌び出すだけです。 圌女は同じこずをしたすが、それが䜕であるか、どのように始たり、どのように機胜するかを説明し理解するこずははるかに明確です。


りィゞェットクラス


Flutterでは、すべおがりィゞェットで構成されおいたす。 DutterバヌゞョンのFlutterでは、各りィゞェットは、Flutterからりィゞェットの特別なクラスを継承するクラスずしお実装されたす。


Goにはクラスがなく、それに応じおクラス階局もありたせん。これは、䞖界がオブゞェクト指向ではなく、さらに階局が䜎いためです。 クラス指向のOOPモデルのみに粟通しおいるプログラマヌにずっお、これは啓瀺かもしれたせんが、実際にはそうではありたせん。 䞖界は、抂念、プロセス、盞互䜜甚の巚倧な織り亀ぜたグラフです。 完党に構造化されおいるわけではありたせんが、混oticずしおいるわけではありたせん。クラス階局にそれを詰め蟌もうずするこずは、コヌドベヌスを読みにくく䞍噚甚にする最も信頌できる方法です。



Goの䜜成者がこのナビキタスなクラスの抂念を再考するのに苊劎し、Goで実装されたOOPのはるかにシンプルで匷力な抂念を実装したため、Goは本圓に感謝しおいたす 。


Goでは、特定のタむプ-構造の圢匏で抜象化を衚したす。


 type MyApp struct { // ... } 

MyAppバヌゞョンのFlutterでは、 MyAppはStatelessWidgetを継承し、 buildメ゜ッドをオヌバヌラむドする必芁がありたす。 これは、2぀の問題を解決するために必芁です。


  1. りィゞェット MyApp にいく぀かの特別なプロパティ/メ゜ッドを䞎えたす
  2. Flutterがビルド/レンダリングプロセスでコヌドを呌び出すこずができるようにしたす

Flutterの内郚はわからないので、アむテム番号1は問題ではないので、やらなければなりたせん。 Goには、このためのナニヌクで明癜な解決策がありたす 埋め蟌み型


 type MyApp struct { flutter.Core // ... } 

このコヌドは、すべおのflutter.Coreプロパティずメ゜ッドをMyAppタむプに远加しMyApp 。 私はそれをWidget代わりにCoreず呌びたした。第䞀に、タむプ埋め蟌みはMyAppただりィゞェットにしないからです。第二に、この名前はGopherJS VectyフレヌムワヌクGo専甚のReactのようなもので非垞によく䜿甚されたす。 VectyずFlutterの類䌌性に぀いおは、埌ほど觊れたす。


2番目のポむント-Flutter゚ンゞンを䜿甚できるbuild()メ゜ッドの実装も、Goで簡単か぀明確に解決されたす。 Goの架空のFlutterラむブラリのどこかで定矩された特定のむンタヌフェむスを満たす特定のシグネチャを持぀メ゜ッドを远加するだけです。


flutter.go


 type Widget interface { Build(ctx BuildContext) Widget } 

そしお今、main.go


 type MyApp struct { flutter.Core // ... } // Build renders the MyApp widget. Implements Widget interface. func (m *MyApp) Build(ctx flutter.BuildContext) flutter.Widget { return flutter.MaterialApp() } 

ここでいく぀かの違いに気付くこずができたす



したがっお、Flutter on Goでりィゞェットを䜜成するには、 flutter.Core型を埋め蟌み、 flutter.Widgetむンタヌフェむスを実装するflutter.Widgetたす。 私たちはそれを理解し、さらに掘り䞋げたした。


状態


これはFlutterで私を本圓に混乱させたものの1぀でした。 StatelessWidgetずStatefulWidget 2぀の異なるクラスがありたす。 私に関しおは、「ステヌトレスりィゞェット」は同じりィゞェットですが、うヌん、デヌタ、状態がありたせん。なぜ新しいクラスを考え出す必芁があるのでしょうか。 しかし、倧䞈倫、私はそれで生きるこずができたす。


しかし、さらに-さらに、別のクラス StatefulWidget を継承するこずはできたせんが、そのような魔法を蚘述する必芁がありたすIDEがあなたのためにそれを行いたすが、ポむントは行いたせん。


 class MyHomePage extends StatefulWidget { @override _MyHomePageState createState() => _MyHomePageState(); } class _MyHomePageState extends State<MyHomePage> { int _counter = 0; void _incrementCounter() { setState(() { _counter++; }); } @override Widget build(BuildContext context) { return Scaffold() } } 

うヌん、ここで䜕が起こるか芋おみたしょう。


基本的に、タスクは次のずおりです。りィゞェットこの堎合はカりンタヌに状態を远加し、りィゞェットを再描画するために状態を倉曎したずきにFlutter゚ンゞンに通知したす。 これが問題の実際の耇雑さですBrooksの甚語での本質的な耇雑さ。


他のすべおは偶然の耇雑さです。 DartのFlutterには、ゞェネリックを䜿甚しおりィゞェットを型パラメヌタヌずしお受け取る新しいStateクラスがありたす。 次に、 _MyHomePageStateクラスが_MyHomePageState 。このクラスはState MyAppを継承State MyApp ... _MyHomePageState 、それでも䜕らかの方法でダむゞェストできたす。 しかし、なぜりィゞェットが存圚するクラスではなく、Stateクラスでbuild()メ゜ッドが定矩されおいるのでしょうか Brrr ....


Flutter FAQにはこの質問に察する答えがあり、 ここでは短い答えを十分に詳现に怜蚎したす StatefulWidget継承するずきに特定のクラスのバグを回避するためです。 ぀たり、これはクラス指向のOOP蚭蚈の問題を解決するための回避策です。 シック。


Goでこれをどのように行いたすか


第䞀に、私は個人的には「州」に別の゚ンティティを䜜成しないこずを奜みたす- State 。 結局、特定のタむプごずにすでに状態がありたす-これらは構造䜓の単なるフィヌルドです。 蚀語は、いわばこの゚ッセンスをすでに䞎えおくれたした。 同様の別の゚ンティティを䜜成するず、プログラマが混乱するだけです。


もちろん、課題は、Flutterに状態の倉化に察応する機胜を提䟛するこずですこれは結局、リアクティブプログラミングの本質です。 そしお、開発者に特別な関数 setState() の䜿甚を「䟝頌」できる堎合、同じ方法で、い぀再描画するかしないかを゚ンゞンに䌝えるために、特別な関数を䜿甚するように䟝頌できたす。 最終的に、すべおの状態の倉曎が再描画を必芁ずするわけではありたせん。ここでさらに制埡できたす。


 type MyHomePage struct { flutter.Core counter int } // Build renders the MyHomePage widget. Implements Widget interface. func (m *MyHomePage) Build(ctx flutter.BuildContext) flutter.Widget { return flutter.Scaffold() } // incrementCounter increments widgets's counter by one. func (m *MyHomePage) incrementCounter() { m.counter++ flutter.Rerender(m) // or m.Rerender() // or m.NeedsUpdate() } 

さたざたな呜名オプションをNeedsUpdate()こずができたす-盎接性ず、これがりィゞェットプロパティ flutter.Coreからflutter.Core であるずいう事実のためにNeedsUpdate()奜きNeedsUpdate()が、グロヌバルflutter.Rerender()メ゜ッドも良いようです。 確かに、りィゞェットはすぐに再描画されるずいう誀った感芚を䞎えたすが、そうではありたせん-次のフレヌム曎新で再描画され、メ゜ッド呌び出しの頻床はレンダリング頻床よりもはるかに高くなる可胜性がありたすが、Flutter゚ンゞンは既にこれを凊理できるはずです


しかし、アむデアは、远加するこずなく必芁な問題を解決しただけです。



さらに、APIははるかに明確で理解しやすい-カりンタヌを増やしお他のプログラムず同じように、Flutterにりィゞェットの再描画を䟝頌したす。 これは、単にsetState堎合にはあたり明らかではないものです。これは、単に状態を蚭定するための特別な関数ではなく、関数wtfを返す関数です。 繰り返しになりたすが、蚀語ずフレヌムワヌクに隠された魔法は、コヌドの理解ず読み取りを非垞に困難にしたす。


私たちの堎合、同じ問題を解決したした。コヌドはよりシンプルで、2倍短くなりたした。


他のりィゞェットの状態りィゞェット


トピックの論理的な続きずしお、「状態りィゞェット」がFlutterの別のりィゞェットでどのように䜿甚されるかを芋おみたしょう。


 @override Widget build(BuildContext context) { return MaterialApp( title: 'Flutter Demo', home: MyHomePage(title: 'Flutter Demo Home Page'), ); } 

ここのMyHomePageは「状態りィゞェット」カりンタヌがあるであり、ビルド䞭にコンストラクタヌMyHomePage()呌び出しお䜜成したす...埅っお、䜕ですか


build()は、りィゞェットを再描画するために呌び出されたすが、1秒に䜕回も実行される可胜性がありたす。 レンダリング䞭に毎回、特に状態を持぀りィゞェットを䜜成する必芁があるのはなぜですか 意味がありたせん


Flutterは、この初期化/状態管理をプログラマヌから隠すために、 WidgetずState間のこの分離を䜿甚するこずがわかりたすもっず隠れたもの、もっず。 毎回新しいりィゞェットを䜜成したすが、すでに䜜成されおいる堎合は自動的に状態を芋぀けおりィゞェットに添付したす。 この魔法は目に芋えないずころで起こり、どのように機胜するのか分かりたせん。コヌドを読む必芁がありたす。


私は、人間工孊で正圓化するこずを可胜な限りプログラマヌに隠したり隠したりするこずは、プログラミングの本圓の悪だず考えおいたす。 平均的な統蚈プログラマヌは、この魔法がどのように機胜するかを理解するためにFlutterコヌドを読たず、盞互接続の方法ず内容を理解する可胜性は䜎いず確信しおいたす。


Goバヌゞョンでは、このような隠された゜ヌサリヌは絶察に望たないでしょうし、たずえそれが少し根拠のないコヌドであっおも、明瀺的で目に芋える初期化を奜むでしょう。 Dutterに察するFlutterのアプロヌチも実装できたすが、魔法を最小限に抑えるためにGoが倧奜きです。フレヌムワヌクでも同じ哲孊を芋おみたいず思いたす。 したがっお、りィゞェットツリヌに状態を持぀りィゞェットのコヌドは、次のように蚘述したす。


 // MyApp is our top application widget. type MyApp struct { flutter.Core homePage *MyHomePage } // NewMyApp instantiates a new MyApp widget func NewMyApp() *MyApp { app := &MyApp{} app.homePage = &MyHomePage{} return app } // Build renders the MyApp widget. Implements Widget interface. func (m *MyApp) Build(ctx flutter.BuildContext) flutter.Widget { return m.homePage } // MyHomePage is a home page widget. type MyHomePage struct { flutter.Core counter int } // Build renders the MyHomePage widget. Implements Widget interface. func (m *MyHomePage) Build(ctx flutter.BuildContext) flutter.Widget { return flutter.Scaffold() } // incrementCounter increments app's counter by one. func (m *MyHomePage) incrementCounter() { m.counter++ flutter.Rerender(m) } 

このコヌドは、りィゞェットツリヌからhomePageを削陀しお別のものに眮き換える堎合、1぀ではなく3぀の堎所で削陀する必芁があるずいう点で、Dartバヌゞョンを倱いhomePage 。 しかし、その芋返りずしお、䜕が、どこで、どのように発生するのか、メモリがどこに割り圓おられるのか、誰が誰を呌び出すのかなどの完党な画像を取埗したす。手のひらのコヌドは明確で読みやすいです。


ちなみに、FlutterにはStatefulBuilderのようなものもありたす。これにより、さらに魔法が远加され、状態がオンザフラむのりィゞェットを䜜成できたす。


DSL


それでは、楜しいこずをしおみたしょう。 Goでりィゞェットツリヌをどのように衚珟したすか 簡朔で、きれいで、リファクタリングず倉曎が簡単で、りィゞェット芖芚的に近く、近くにあり蚘述内にある必芁があるりィゞェット間の空間的な関係を蚘述し、同時に任意のむベントハンドラのようなコヌド。


Dartのオプションは非垞に矎しく雄匁であるように思えたす。


 return Scaffold( appBar: AppBar( title: Text(widget.title), ), body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ Text('You have pushed the button this many times:'), Text( '$_counter', style: Theme.of(context).textTheme.display1, ), ], ), ), floatingActionButton: FloatingActionButton( onPressed: _incrementCounter, tooltip: 'Increment', child: Icon(Icons.add), ), ); 

各りィゞェットにはオプションのパラメヌタヌを受け入れるコンストラクタヌがあり、ここでレコヌドを本圓に玠晎らしいものにしおいるのは、関数の名前付きパラメヌタヌです 。


名前付きパラメヌタヌ


この甚語に慣れおいない堎合、倚くの蚀語では、関数の䜍眮は関数にずっお重芁であるため、関数のパラメヌタヌは「䜍眮」ず呌ばれたす。


 Foo(arg1, arg2, arg3) 

、および名前付きパラメヌタヌの堎合、すべおが呌び出しの名前によっお決定されたす。


 Foo(name: arg1, description: arg2, size: arg3) 

これはテキストを远加したすが、パラメヌタヌの意味を理解しようずしお、クリックを保持し、コヌド内を移動したす。


りィゞェットツリヌの堎合、読みやすさにおいお重芁な圹割を果たしたす。 䞊蚘ず同じコヌドを、名前付きパラメヌタヌなしで比范したす。


 return Scaffold( AppBar( Text(widget.title), ), Center( Column( MainAxisAlignment.center, <Widget>[ Text('You have pushed the button this many times:'), Text( '$_counter', Theme.of(context).textTheme.display1, ), ], ), ), FloatingActionButton( _incrementCounter, 'Increment', Icon(Icons.add), ), ); 

そうではありたせん。 そう 理解するのが難しいだけではありたせん各パラメヌタヌの意味ずそのタむプを芚えおおく必芁があり、これは重芁な認知的負荷ですだけでなく、転送するパラメヌタヌを自由に遞択するこずもできたせん。 たずえば、マテリアルアプリケヌションにFloatingActionButtonを䜿甚したくない堎合がありたす。そのため、パラメヌタヌでFloatingActionButtonを指定しないでください。 名前付きパラメヌタヌがない堎合、可胜なすべおのりィゞェットを匷制的に指定するか、リフレクションを䜿甚しおマゞックを䜿甚しお、どのりィゞェットが転送されたかを調べる必芁がありたす。


たた、Goには関数ず名前付きパラメヌタヌのオヌバヌロヌドがないため、これはGoにずっお簡単なタスクではありたせん。


Goりィゞェットツリヌ


バヌゞョン1


Scaffoldオブゞェクトを詳しく芋おみたしょう。これは、モバむルアプリケヌションの䟿利なラッパヌです。 appBar、drawe、home、bottomNavigationBar、floatingActionBarのプロパティがあり、これらはすべおりィゞェットです。 りィゞェットツリヌを䜜成するずき、実際には䜕らかの方法でこのオブゞェクトを初期化し、前述のりィゞェットプロパティを枡す必芁がありたす。 さお、これはオブゞェクトの通垞の䜜成ず初期化ずあたり倉わらない。


額のアプロヌチを詊しおみたしょう


 return flutter.NewScaffold( flutter.NewAppBar( flutter.Text("Flutter Go app", nil), ), nil, nil, flutter.NewCenter( flutter.NewColumn( flutter.MainAxisCenterAlignment, nil, []flutter.Widget{ flutter.Text("You have pushed the button this many times:", nil), flutter.Text(fmt.Sprintf("%d", m.counter), ctx.Theme.textTheme.display1), }, ), ), flutter.FloatingActionButton( flutter.NewIcon(icons.Add), "Increment", m.onPressed, nil, nil, ), ) 

最も矎しいUIコヌドではありたせん。 flutterずいう蚀葉flutterどこにでもあり、尋ねたす。 非衚瀺にするために実際には、 flutterではなく、本質ではなくパッケヌゞmaterialに名前を付ける必芁がありたした、名前のないパラメヌタヌは完党に明癜ではなく、これらのnilはどこでも公然ず混乱しおいたす。


バヌゞョン2


それでも、ほずんどのコヌドはflutterパッケヌゞのいずれかのタむプ/関数を䜿甚するため、「ドットむンポヌト」圢匏を䜿甚しおパッケヌゞをネヌムスペヌスにむンポヌトし、パッケヌゞ名を「隠す」こずができたす。


 import . "github.com/flutter/flutter" 

flutter.Text代わりに、 Textだけを曞くこずができたす。 これは通垞、悪い習慣ですが、私たちはフレヌムワヌクで䜜業しおおり、このむンポヌトは文字通りすべおの行にありたす。 私の緎習から、これはたさにそのようなむンポヌトが受け入れられる堎合です-䟋えば、 GoConveyをテストするために玠晎らしいフレヌムワヌクを䜿甚するずきのように。


コヌドがどのように芋えるか芋おみたしょう


 return NewScaffold( NewAppBar( Text("Flutter Go app", nil), ), nil, nil, NewCenter( NewColumn( MainAxisCenterAlignment, nil, []Widget{ Text("You have pushed the button this many times:", nil), Text(fmt.Sprintf("%d", m.counter), ctx.Theme.textTheme.display1), }, ), ), FloatingActionButton( NewIcon(icons.Add), "Increment", m.onPressed, nil, nil, ), ) 

すでに優れおいたすが、これらのnil-sず名前のないパラメヌタヌ....


バヌゞョン3


枡されたパラメヌタヌを分析するためにリフレクションプログラムの実行䞭にコヌドを怜査する機胜を䜿甚した堎合のコヌドの倖芳を芋おみたしょう。 このアプロヌチは、Goの初期のHTTPフレヌムワヌクたずえばmartini で䜿甚されおおり、非垞に悪いプラクティスず芋なされたす-安党ではなく、型システムの利䟿性を倱い、比范的遅く、コヌドに魔法を远加したす-しかし、実隓のために詊すこずができたす


 return NewScaffold( NewAppBar( Text("Flutter Go app"), ), NewCenter( NewColumn( MainAxisCenterAlignment, []Widget{ Text("You have pushed the button this many times:"), Text(fmt.Sprintf("%d", m.counter), ctx.Theme.textTheme.display1), }, ), ), FloatingActionButton( NewIcon(icons.Add), "Increment", m.onPressed, ), ) 

悪くはありたせん。たた、Dartのオリゞナルバヌゞョンのように芋えたすが、名前付きパラメヌタヌが䞍足しおいるため、実際に目が痛くなっおいたす。


バヌゞョン4


少し戻っお、䜕をしようずしおいるのか自問しおみたしょう。 Dartのアプロヌチをやみくもにコピヌする必芁はありたせんこれは玠晎らしいボヌナスですが、DartのFlutterに既に粟通しおいる人々から孊ぶこずは少なくなりたす。 基本的に、新しいオブゞェクトを䜜成しおプロパティを割り圓おるだけです。


この方法で詊すこずができたすか


 scaffold := NewScaffold() scaffold.AppBar = NewAppBar(Text("Flutter Go app")) column := NewColumn() column.MainAxisAlignment = MainAxisCenterAlignment counterText := Text(fmt.Sprintf("%d", m.counter)) counterText.Style = ctx.Theme.textTheme.display1 column.Children = []Widget{ Text("You have pushed the button this many times:"), counterText, } center := NewCenter() center.Child = column scaffold.Home = center icon := NewIcon(icons.Add), fab := NewFloatingActionButton() fab.Icon = icon fab.Text = "Increment" fab.Handler = m.onPressed scaffold.FloatingActionButton = fab return scaffold 

このアプロヌチは機胜し、「名前付きパラメヌタヌ」の問題を解決したすが、りィゞェットツリヌの党䜓像を混乱させたす。 たず、りィゞェットを定矩する順序が逆になりたす。りィゞェットが深くなるほど、りィゞェットを早く䜜成する必芁がありたす。 第二に、コヌドの䟿利な芖芚的構造を倱いたした。むンデントを䜿甚しおも、ツリヌ内のりィゞェットの深さがすぐにわかりたす。


ずころで、このアプロヌチはGTKやQtのようなUIフレヌムワヌクで長い間䜿甚されおきたした。 , , Qt 5:


  QGridLayout *layout = new QGridLayout(this); layout->addWidget(new QLabel(tr("Object name:")), 0, 0); layout->addWidget(m_objectName, 0, 1); layout->addWidget(new QLabel(tr("Location:")), 1, 0); m_location->setEditable(false); m_location->addItem(tr("Top")); m_location->addItem(tr("Left")); m_location->addItem(tr("Right")); m_location->addItem(tr("Bottom")); m_location->addItem(tr("Restore")); layout->addWidget(m_location, 1, 1); QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, this); connect(buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject); connect(buttonBox, &QDialogButtonBox::accepted, this, &QDialog::accept); layout->addWidget(buttonBox, 2, 0, 1, 2); 

, - . , , , .


5


, – -. 䟋


 func Build() Widget { return NewScaffold(ScaffoldParams{ AppBar: NewAppBar(AppBarParams{ Title: Text(TextParams{ Text: "My Home Page", }), }), Body: NewCenter(CenterParams{ Child: NewColumn(ColumnParams{ MainAxisAlignment: MainAxisAlignment.center, Children: []Widget{ Text(TextParams{ Text: "You have pushed the button this many times:", }), Text(TextParams{ Text: fmt.Sprintf("%d", m.counter), Style: ctx.textTheme.display1, }), }, }), }), FloatingActionButton: NewFloatingActionButton( FloatingActionButtonParams{ OnPressed: m.incrementCounter, Tooltip: "Increment", Child: NewIcon(IconParams{ Icon: Icons.add, }), }, ), }) } 

わあ , . ...Params , . , , Go , , .


-, ...Params , . (proposal) — " " . , FloatingActionButtonParameters{...} {...} . :


 func Build() Widget { return NewScaffold({ AppBar: NewAppBar({ Title: Text({ Text: "My Home Page", }), }), Body: NewCenter({ Child: NewColumn({ MainAxisAlignment: MainAxisAlignment.center, Children: []Widget{ Text({ Text: "You have pushed the button this many times:", }), Text({ Text: fmt.Sprintf("%d", m.counter), Style: ctx.textTheme.display1, }), }, }), }), FloatingActionButton: NewFloatingActionButton({ OnPressed: m.incrementCounter, Tooltip: "Increment", Child: NewIcon({ Icon: Icons.add, }), }, ), }) } 

Dart! .


6


, . , , , , .


, , , -, – :


 button := NewButton(). WithText("Click me"). WithStyle(MyButtonStyle1) 

たたは


 button := NewButton(). Text("Click me"). Style(MyButtonStyle1) 

Scaffold- :


 // Build renders the MyHomePage widget. Implements Widget interface. func (m *MyHomePage) Build(ctx flutter.BuildContext) flutter.Widget { return NewScaffold(). AppBar(NewAppBar(). Text("Flutter Go app")). Child(NewCenter(). Child(NewColumn(). MainAxisAlignment(MainAxisCenterAlignment). Children([]Widget{ Text("You have pushed the button this many times:"), Text(fmt.Sprintf("%d", m.counter)). Style(ctx.Theme.textTheme.display1), }))). FloatingActionButton(NewFloatingActionButton(). Icon(NewIcon(icons.Add)). Text("Increment"). Handler(m.onPressed)) } 

Go – , . Dart-, :



New...() – , . , — " , , , , , , – " .


, , 5- 6- .



"hello, world" Flutter Go:


main.go


 package hello import "github.com/flutter/flutter" func main() { flutter.Run(NewMyApp()) } 

app.go:


 package hello import . "github.com/flutter/flutter" // MyApp is our top application widget. type MyApp struct { Core homePage *MyHomePage } // NewMyApp instantiates a new MyApp widget func NewMyApp() *MyApp { app := &MyApp{} app.homePage = &MyHomePage{} return app } // Build renders the MyApp widget. Implements Widget interface. func (m *MyApp) Build(ctx BuildContext) Widget { return m.homePage } 

home_page.go:


 package hello import ( "fmt" . "github.com/flutter/flutter" ) // MyHomePage is a home page widget. type MyHomePage struct { Core counter int } // Build renders the MyHomePage widget. Implements Widget interface. func (m *MyHomePage) Build(ctx BuildContext) Widget { return NewScaffold(ScaffoldParams{ AppBar: NewAppBar(AppBarParams{ Title: Text(TextParams{ Text: "My Home Page", }), }), Body: NewCenter(CenterParams{ Child: NewColumn(ColumnParams{ MainAxisAlignment: MainAxisAlignment.center, Children: []Widget{ Text(TextParams{ Text: "You have pushed the button this many times:", }), Text(TextParams{ Text: fmt.Sprintf("%d", m.counter), Style: ctx.textTheme.display1, }), }, }), }), FloatingActionButton: NewFloatingActionButton( FloatingActionButtonParameters{ OnPressed: m.incrementCounter, Tooltip: "Increment", Child: NewIcon(IconParams{ Icon: Icons.add, }), }, ), }) } // incrementCounter increments app's counter by one. func (m *MyHomePage) incrementCounter() { m.counter++ flutter.Rerender(m) } 

!


おわりに


Vecty


, , Vecty . , , , , Vecty DOM/CSS/JS, Flutter , 120 . , Vecty , Flutter Go Vecty .


Flutter


– , . Flutter, .


Go


" Flutter Go?" "" , , , , , Flutter, , , "" . , Go .


, Go . . Go, , , -. – , , .


Go. – , .


Flutter


, Flutter , , . "/ " , Dart ( , , ). Dart, , (, ) DartVM V8, Flutter – Flutter -.


, . . , , 1.0 . , - .


game changer, Flutter , , .


UI – Flutter, .


参照資料




Source: https://habr.com/ru/post/J435960/


All Articles