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

Flutter研修【MIXI 23新卒技術研修】

Flutter研修【MIXI 23新卒技術研修】

23新卒技術研修で実施したFlutter研修の講義資料です。

動画:https://youtu.be/9IqUQ2TXacI

ハンズオン用リポジトリ:https://github.com/mixigroup/2023BeginnerTrainingFlutter

資料の利用について
公開している資料は勉強会や企業の研修などで自由にご利用頂いて大丈夫ですが、以下の形での利用だけご遠慮ください。
・受講者から参加費や授業料などを集める形での利用(会場費や飲食費など勉強会運営に必要な実費を集めるのは問題ありません)
・出典を削除または改変しての利用

MIXI ENGINEERS

April 28, 2023
Tweet

More Decks by MIXI ENGINEERS

Other Decks in Technology

Transcript

  1. ࣄલ४උ͸0,ʁ J04ಈ͔͍ͨ͠ਓɹ "OESPJEಈ͔͍ͨ͠ਓɹ w 9DPEFͷΠϯετʔϧ͓Αͼղౚ w Πϯετʔϧ͸"QQ4UPSFͰ͸ͳ͘EFWFMPQFSαΠτ͔Βམͱͯ͘͠Δ͜ͱΛ͓קΊ w IUUQTEFWFMPQFSBQQMFDPNEPXOMPBENPSF w

    ࣄલʹ"QQMF*%͕ඞཁ w ձࣾͷϝʔϧΞυϨεͰΞΧ΢ϯτΛ࡞੒ w "OESPJE4UVEJPͷΠϯετʔϧ͓Αͼղౚ w Ұ୴ىಈ͠ͳ͍ͱ fl VUUFSEPDUPSͨ͠ͱ͖ʹ6OBCMFUPMPDBUF"OESPJE4%,ͷΤϥʔʹͳΔ
  2. ຊ೔ͷ͓඼ॻ͖ ʙ'MVUUFSͱ͸ ʙ fl VUUFSDSFBUFίϚϯυͰΞϓϦΛ࡞ͬͯΈΑ͏ʂ ʙٳܜ ʙDSFBUF͞ΕͨΞϓϦΛݟ͍ͯ͜͏ʂ *OUSPEVDUJPO 4UBUF 5FYU'JFME

    ը໘ભҠʢ/BWJHBUPSʣ ʙϥϯν ʙωοτϫʔΫ௨৴ʢIUUQ௨৴ʣ ʙνʔϜͰνϟϨϯδʂ 
 ɹɹɹɹ$IBU(15ͱͷνϟοτΞϓϦΛ࡞ͬͯΈΑ͏ʂ ʙΫϩʔδϯά
  3. 'MVUUFSͱ͸ w ϚϧνϓϥοτϑΥʔϜ։ൃ͕ՄೳͳϑϨʔϜϫʔΫ w ̓ͭͷϓϥοτϑΥʔϜ্Ͱಈ͘ΞϓϦΛ࡞ΕΔʂ w ੈքʹ͸ສਓҎ্ͷ։ൃऀͱສҎ্ͷΞϓϦ͕͋Δ w (JU)VCͷίϯτϦϏϡʔλʔ਺͸74$PEF IPNFBTTJTUBOUʹ͍࣍ͰҐʂ

    w %Ϟσϧͷදࣔ΋Ͱ͖ΔΑ͏ʹʂ 'MVUUFS'PSXBSEIUUQTXXXZPVUVCFDPNXBUDI W[,2:(,"F8 %ϞσϧදࣔΛࢼͯ͠ΈΔIUUQTJUPNFUFBNCMPH fl VUUUFSTDFOFNFNP
  4. w %BSUͱ͍͏ݴޠͰ࣮૷͢Δ w (PPHMF͕+BWB4DSJQUͷ໰୊఺Λվળͨ͠୅ସݴޠͱͯ͠೥ʹ։ൃ͞Εͨ΋ͷ w %BSUͰ/VMM4BGFUZʹͳͬͨʢผϖʔδͰઆ໌ʣ w ϨϯμϦϯάΤϯδϯ΋4LJBΛ࢖ͬͯࣗલͰ࡞ΒΕ͍ͯΔͷͰ଎͍ʂ w 'MVUUFS'PSXBSEͰ৽ϨϯμϦϯάΤϯδϯͷ*NQFMMFS͕ެ։͞Εͨ

    w એݴత6*Ͱॻ͘͜ͱ͕ՄೳʢผϖʔδͰઆ໌ʣ w 4UPSZCPBSEΛ࢖ͬͨ4XJGUͷίʔυΑΓ3FBDUͷํ͕ࣅͯΔ͔΋ 'MVUUFSͱ͸ 'MVUUFSͷΞʔΩςΫνϟIUUQTEPDT fl VUUFSEFWSFTPVSDFTBSDIJUFDUVSBMPWFSWJFX *NQFMMFSʹ͍ͭͯIUUQTEPDT fl VUUFSEFWQFSGJNQFMMFS EBTI܅ʹ͍ͭͯIUUQTEPDT fl VUUFSEFWEBTI
  5. ࣮ߦ࣌ʹOVMMͷΤϥʔͰ མͪΔ͜ͱ͸ͳ͘ͳΔ /VMM4BGFUZͬͯʁ جຊతʹOVMM࢖ͬͪΌμϝ ࢖͍͍ͨ࣌͸ Λ͚ͭΔ int a = 100;

    int? b = null; a = 100; print(a + b); // Τϥʔ if (b != null) { print(a + b); } print(a + b!); C͕OVMMͷ࣌͸ආ͚ ͯ͘ΕΔͷͰ҆৺ OVMMTBGFUZʹ͍ͭͯIUUQTEBSUEFWOVMMTBGFUZ
  6. label = UILabel() label.text = “Babu~” label.textColor = .black label.textAlignment

    = .center view.addSubview(label) Text( “Babu~", style: TextStyle(color: Colors.black), textAlign: TextAlign.center, ), ໋ྩతʢ4XJGUʣ એݴత6*ͬͯʁ એݴతʢ%BSUʣ ϥϕϧΛ࡞Εʂ ϥϕϧͷςΩετ͸όϒʙͰ͋Εʂ ৭͸ࠇͰ͋ΕʂਅΜதدͤͰ͋Εʂ ͦͷϥϕϧΛ7JFXʹ௥Ճͤ͑ʂ
  7. label = UILabel() label.text = “Babu~” label.textColor = .black label.textAlignment

    = .center view.addSubview(label) Text( “Babu~", style: TextStyle(color: Colors.black), textAlign: TextAlign.center, ), ໋ྩతʢ4XJGUʣ એݴత6*ͬͯʁ એݴతʢ%BSUʣ զ͸όϒʙͱ͍͏ࠇ৭ͷ ਅΜதدͤςΩετͰ͋Δʂ
  8. ΞϓϦΛ࡞ͬͯΈΑ͏ $ flutter create <<ϓϩδΣΫτͷ໊લ>> $ cd <<ϓϩδΣΫτͷ໊લ>> $ open

    iOS/Runner.xcworkspace // ios ͷਓͷΈ $ flutter run "OESPJEͷਓ͸࣮ػબ୒΋͘͠͸ "OESPJEελδΦ্ཱͪ͛ͯΤϛϡબ୒ ϓϩδΣΫτ໊͸ΞϯμόʔͰܨ͕ͳ͍ͱ ʰzϓϩδΣΫτ໊zJTOPUBWBMJE%BSUQBDLBHFOBNFʱ ͬͯΤϥʔుౖ͍ͯΒΕΔ
  9. *OUSPEVDUJPO w ϥΠϒίʔσΟϯά͠·͢ʂ w ϓϩδΣΫτʢσΟϨΫτϦʣߏ੒ʹ͍ͭͯ w NBJO ͷྲྀΕ΍DMBTTͷઆ໌ w .Z)PNF1BHFͷϑΝΠϧ෼͚ͯΈΔ

    w ଞͷϑΝΠϧΛࢀর͢Δͱ͖͸JNQPSU͢Δ w 5FYUͷத਎Λม͑ͯΈͨΓ͢Δ w )PU3FMPBE3FTUBSUͱ͸ʁʢผϖʔδͰઆ໌ʣ w .Z)PNF1BHFݟͯ͘ w 4DB ff PMEͱ͔DPMVNOͳͲඪ४΢ΟδΣοτ͕ͨ͘͞ΜʂʢผϖʔδͰઆ໌ʣ w ֦ுػೳ͸͜͏࢖͏ʂʢผϖʔδͰઆ໌ʣ
  10. )PUSFMPBESFTUBSUͱ͸ʁ )PUSFMPBE )PUSFTUBSU ͍͍ͪͪDUSMD͔Βͷ fl VUUFSSVO͠ͳͯ͘େৎ෉ʂʂʂʂ λʔϛφϧͰ3Λԡ͢ ΄΅Ϧηοτ͞ΕΔ λʔϛφϧͰSΛԡ͢ 5FYU΍৭ͳͲ΢ΟδΣοτΛ

    มߋͨ͠Β൓ө͞ΕΔ 4UBUF͸ͦͷ·· ʢ4UBUFʹؔͯ͠͸ޙͰઆ໌ʣ fl VUUFSSVO ωΠςΟϒίʔυ͔Β ࣮ߦ͠௚͢ ˞)PUSFMPBE͕Ͱ͖Δͷ͸σόοάϏϧυ࣌ʢ+*5ίϯύΠϧ࣌ʣͷΈ
  11. $PMVNOͷதʹ-JTU7JFXΛೖΕΔͱ͖͸஫ҙʂ w -JTU7JFX΋޿͕Ζ͏ͱͯ͘͠Δੑ࣭Λ࣋ͭͷͰΤϥʔʹͳΓ·͢ 5IFGPMMPXJOH3FOEFS0CKFDUXBTCFJOHQSPDFTTFEXIFOUIFFYDFQUJPOXBT fi SFE 3FOEFS7JFXQPSUD/&&%4-":065/&&%41"*/5/&&%4$0.104*5*/(#*5461%"5& OFFETDPNQPTJUJOH DSFBUPS7JFXQPSUˡ*HOPSF1PJOUFS<(MPCBM,FZBEC>ˡ4FNBOUJDTˡ-JTUFOFSˡ @(FTUVSF4FNBOUJDTˡ

    3BX(FTUVSF%FUFDUPS<-BCFMFE(MPCBM,FZ3BX(FTUVSF%FUFDUPS4UBUFD>ˡ-JTUFOFSˡ @4DSPMMBCMF4DPQF ˡ@4DSPMM4FNBOUJDT<(MPCBM,FZB>ˡ/PUJ fi DBUJPO-JTUFOFS4DSPMM.FUSJDT/PUJ fi DBUJPOˡ 4DSPMMBCMFˡ1SJNBSZ4DSPMM$POUSPMMFSˡl QBSFOU%BUBOPOF DBOVTFTJ[F  DPOTUSBJOUT#PY$POTUSBJOUT X I*O fi OJUZ  ɽɽɽ
  12. $PMVNOͷதʹ-JTU7JFXΛೖΕΔͱ͖͸஫ҙʂ w -JTU7JFX΋޿͕Ζ͏ͱͯ͘͠Δੑ࣭Λ࣋ͭͷͰΤϥʔʹͳΓ·͢ 5IFGPMMPXJOH3FOEFS0CKFDUXBTCFJOHQSPDFTTFEXIFOUIFFYDFQUJPOXBT fi SFE 3FOEFS7JFXQPSUD/&&%4-":065/&&%41"*/5/&&%4$0.104*5*/(#*5461%"5& OFFETDPNQPTJUJOH DSFBUPS7JFXQPSUˡ*HOPSF1PJOUFS<(MPCBM,FZBEC>ˡ4FNBOUJDTˡ-JTUFOFSˡ @(FTUVSF4FNBOUJDTˡ

    3BX(FTUVSF%FUFDUPS<-BCFMFE(MPCBM,FZ3BX(FTUVSF%FUFDUPS4UBUFD>ˡ-JTUFOFSˡ @4DSPMMBCMF4DPQF ˡ@4DSPMM4FNBOUJDT<(MPCBM,FZB>ˡ/PUJ fi DBUJPO-JTUFOFS4DSPMM.FUSJDT/PUJ fi DBUJPOˡ 4DSPMMBCMFˡ1SJNBSZ4DSPMM$POUSPMMFSˡl QBSFOU%BUBOPOF DBOVTFTJ[F  DPOTUSBJOUT#PY$POTUSBJOUT X I*O fi OJUZ  ɽɽɽ *O fi OJUZʂʂ
  13. 5SZഒʹͳΔTUBUFΛ௥Ճ͠Α͏ w ৽͍͠4UBUFΛఆٛ w ഒ͢ΔϝιουΛఆٛ w ഒ͢ΔϝιουΛݺͿϘλϯΛ௥Ճ void _twice() {

    setState(() { _counter2 = _counter2 * 2; }); } FloatingActionButton( onPressed: () { _twice(); },
  14. 5SZը໘ભҠͯ͠ΈΑ͏ IUUQTHJUIVCDPNNJYJHSPVQ#FHJOOFS5SBJOJOH'MVUUFSQVMM w /BWJHBUPSͷ΍ΓํͰ͢ w ϥΠϒίʔσΟϯά͠·͢ʂ w 'JSTU1BHFͱ4FDPOE1BHFΛ࡞੒ w 4DB

    ff PMEͳ͍ͱ౔୆͕ͳ͍͔ΒมͳදࣔʹͳͬͪΌ͏Αʙ w QVTIͷઆ໌ʢผϖʔδͰઆ໌ʣ w ͋Β͔͡Ί3PVUFొ࿥͓ͯ͘͠ͱศརͩΑʙ w QPQͷઆ໌ʢผϖʔδͰઆ໌ʣ
  15. ը໘ભҠ " .BUFSJBM"QQ͕͍࣋ͬͯΔ/BWJHBUPSΛ࢖ͬͯը໘ભҠ͢Δ " # .BUFSJBM1BHF3PVUF Navigator.push( context, MaterialPageRoute<void>( builder:

    (BuildContext context) => B(), ), ); Navigator.pop(conte 8JEHFU ࠓճ͸4FDPOE1BHF Λ .BUFSJBM1BHF3PVUFʹ౉ͯ͠ 3PVUFΛ࡞ΓɼͦΕΛදࣔ
  16. .BUFSJBM"QQʹ͋Β͔͡Ί3PVUFΛొ࿥͓ͯ͜͠͏ʂ return MaterialApp( title: 'Flutter Demo', theme: ThemeData( primarySwatch: Colors.pink,

    ), initialRoute: '/', routes: <String, WidgetBuilder>{ '/': (BuildContext context) => const FirstPage(), '/second': (BuildContext context) => const SecondPage(), }, ); ͜ΕͰݺ΂ΔΑ͏ʹͳΔʂ Navigator.pushNamed(context, "/second");
  17. IUUQTHJUIVCDPNNJYJHSPVQ#FHJOOFS5SBJOJOH'MVUUFSQVMM w (JU)VCͷϦϙδτϦҰཡΛऔಘ͢Δ"1*Λୟ͍ͯΈΑ͏ʂ w IUUQTEPDTHJUIVCDPNKBSFTUSFQPTSFQPT BQJ7FSTJPOMJTU SFQPTJUPSJFTGPSBVTFS w ·ͣ͸DVSMίϚϯυͰୟ͍ͯΈΑ͏ w

    'MVUUFSͰIUUQ௨৴͢ΔͨΊʹIUUQύοέʔδΛ͍ΕΑ͏ʂ w IUUQTQVCEFWQBDLBHFTIUUQ 5SZωοτϫʔΫ௨৴ͯ͠ΈΑ͏ $ curl -L https://api.github.com/users/kno3a87/repos ϦϙδτϦҰཡ ͍ͩ͘͞ʙ <\ JE  OPEF@JEIPHF  OBNF)FMMP8PSME  ʜ ωοτϫʔΫ௨৴ ΫϥΠΞϯτ "1*
  18. IUUQTHJUIVCDPNNJYJHSPVQ#FHJOOFS5SBJOJOH'MVUUFSQVMM w ·ͣ͸KTPO͔ΒEBSUͰѻ͑ΔΦϒδΣΫτʹม׵͠Α͏ w IPHF<bGVHB`><bQJZP`>Έ͍ͨͳऔಘํ๏ͩͱจࣈྻUZQPͪ͠Ό͏͔΋ʜ w Ϟσϧʹม׵ͪ͠Ό͓͏ʂ w ࢖༻ύοέʔδ w

    IUUQTQVCEFWQBDLBHFTKTPO@TFSJBMJ[BCMF w IUUQTQVCEFWQBDLBHFTCVJME@SVOOFS 5SZKTPOΛύʔε͠Α͏ $ flutter pub run build_runner build \ lOBNFzlLVOPz lBHFzlz ^ VTFSOBNF͸LVOP VTFSBHF͸ʂ
  19. $IBU(15ͱ͸ʁ w 0QFO"*͕೥݄ʹެ։ͨ͠ਓ޻஌ೳνϟοτϘοτ w ΢ΣϒΞϓϦ͚ͩͰͳ͘"1*΋༻ҙ͞ΕͯΔ w IUUQTQMBUGPSNPQFOBJDPNEPDTBQJSFGFSFODFNBLJOHSFRVFTUT w "1*Λ࢖͏্Ͱͷ஫ҙࣄ߲ w

    ػີ৘ใ΍ୈࡾऀͷ஌తࡒ࢈ݖΛ৵֐͢ΔΑ͏ͳΠϯϓοτ͸͠ͳ͍Ͱʂʂʂʂ w ΋ͪΖΜ㒷ᨱதই΋/( w Ξ΢τϓοτ͸ݸਓͰར༻͢ΔൣғʹͱͲΊ͍ͯͩ͘͞
  20. 5FBN$IBMMFOHF$IBU(15ͱ઀ଓ w $IBU(15"1*ͷτʔΫϯ͸%SPQCPYʹ͋Γ·͢ʂ w (JUʹQVTI͠ͳ͍ͰͶʂʂʂ w FOWϑΝΠϧΛ࡞੒ͯ͠HJUJHOPSFʹॻ͍͓ͯ͘ͱ҆৺͔΋ w LP w

    ͖ͬ͞ͷ౤ߘϖʔδͰॻ͍ͨ಺༰Λ"1*ʹ౤͛ͯΈΑ͏ w ݁Ռ΋දࣔͯ͠ΈΑ͏ʂ ౴͑ IUUQTHJUIVCDPNNJYJHSPVQ#FHJOOFS5SBJOJOH'MVUUFSQVMM $ flutter run —-dart-define=MY_TOKEN=<͜͜ʹτʔΫϯ>
  21. 5FBN$IBMMFOHF#MPDύλʔϯʹॻ͖௚ͯ͠ΈΑ͏ w #MPDύλʔϯͱ͸ঢ়ଶ؅ཧʹؔ͢ΔΞʔΩςΫνϟύλʔϯͷҰͭ w ೥ͷ(PPHMF*0Ͱ঺հ͞Εͨ w ϏδωεϩδοΫͱ6*Λ෼཭ͯ͠։ൃ͠΍͘͢͠Α͏ʂ w IUUQTCMPDMJCSBSZEFW w

    'MVUUFSެࣜαϯϓϧ࣮૷΋͋Δʂ w IUUQTHJUIVCDPN fl VUUFSOFXT@UPPMLJUUSFF DEDFEDGFCCFBBB w 'MVUUFSͷϕετϓϥΫςΟεΛ౿ऻ w ࢖༻ύοέʔδ w IUUQTQVCEFWQBDLBHFT fl VUUFS@CMPD
  22. ΢ΟδΣοτͷ੾Γग़͠ํ class SampleState extends State<Sample> { final text1 = '΄͛ΓΜ';

    final text2 = '͏ͳΓΜ'; @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text(widget.title), ), body: Center( child: Column( children: [ Text(text1), Text(text2), ], ), ), ); } } ଞͷ΢ΟδΣοτͰ΋ ࢖͍·Θ͍ͨ͠ͷͰ ੾Γग़͍ͨ͠ʂ
  23. ΢ΟδΣοτͷ੾Γग़͠ํIFMQFSNFUIPE class SampleState extends State<Sample> { final text1 = '΄͛ΓΜ';

    final text2 = '͏ͳΓΜ'; @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text(widget.title), ), body: Center( child: Column( children: [ Text(text1), Text(text2), ], ), ), ); } } class SampleState extends State<Sample> { final text1 = '΄͛ΓΜ'; final text2 = '͏ͳΓΜ'; @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text(widget.title), ), body: showText(), ); } Widget showText() { return Center( child: Column( children: [ Text(text1), Text(text2), ], ), ); } } ؆୯ʹ੾Γग़ͤΔ
  24. ΢ΟδΣοτͷ੾Γग़͠ํΫϥε8JEHFU class SampleState extends State<Sample> { final text1 = '΄͛ΓΜ';

    final text2 = '͏ͳΓΜ'; @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text(widget.title), ), body: Center( child: Column( children: [ Text(text1), Text(text2), ], ), ), ); } } class SampleState extends State<Sample> { final text1 = '΄͛ΓΜ'; final text2 = '͏ͳΓΜ'; @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text(widget.title), ), body: SampleText( text1: text1, text2: text2, ), ); } } class SampleText extends StatelessWidget { final String text1; final String text2; const SampleText({ super.key, required this.text1, required this.text2, }); @override Widget build(BuildContext context) { return Center( child: Column( children: [ Text(text1), Text(text2), ], ), ); } } Ϋϥεͱͯ͠੾Γग़͢ͱ ͪΐͬͱΊΜͲ͍͚͘͞Ͳ ςετ͠΍͍͢ˍ ແବͳ࠶ඳըΛ཈͑ΒΕΔʂ
  25. #VJME$POUFYUͬͯͳΜͩʁ 8JEHFU͸ӈਤͷΑ͏ʹπϦʔঢ়ʹͳ͍ͬͯΔ #VJME$POUFYU͸݂ےͷ͜ͱͰ૆ઌͷ৘ใʹΞΫηε͢Δ͜ͱ͕Ͱ͖Δ ˞௚ܘͷ૆ઌ͔͠ḷΕͳ͍ʂ ˞ͭͷ8JEHFUΠϯελϯεʹରͯ͠ 
 ͭͷ#VJME$POUFYU͕ϖΞͷؔ܎ʹͳ͍ͬͯΔʂ .BUFSJBM"QQ 5IFNF CMVF

    4DB ff PME 5IFNF QJOL 8JEHFU$ 5IFNF PSBOHF 8JEHFU" $PMVNO 3PX 8JEHFU# 8JEHFU#ͷ݂ےΛḷͬͨΒ ͜͜ͷ5IFNF͕ݟ͔ͭͬͨʂ ͸ࣗ෼ͷ݂ےΛḷͬͯ ૆ઌʹ͋Δ5IFNFΛݟ͚͖͍ͭͯͯΔ Theme.of(context)