Slide 1

Slide 1 text

BLoC Pattern Introduction with Swift 2019.01.20 #shinjukult @to4iki 1

Slide 2

Slide 2 text

Me • @to4iki •  • AbemaTV • ! ☕ ♨ $ 2

Slide 3

Slide 3 text

BLoC? 3

Slide 4

Slide 4 text

Business Logic Component 4

Slide 5

Slide 5 text

DartConf 2018 Flutter / AngularDart – Code sharing, better together 5

Slide 6

Slide 6 text

Google I/O '18 Build reactive mobile apps with Flutter 6

Slide 7

Slide 7 text

BLoC = (Flutterൃ঵ͷ) ঢ়ଶ؅ཧʹؔ͢Δ ΞʔΩςΫνϟύλʔϯ 7

Slide 8

Slide 8 text

Motivation • Web (Angular Dart)ͱMobile (Flutter)ͰϏδωεϩδοΫͷ ίʔυΛڞ༗͍ͨ͠ • ݴޠɾϓϥοτϑΥʔϜΛ໰Θͳ͍ঢ়ଶ؅ཧͷύλʔϯ͕ཉ ͍͠ 8

Slide 9

Slide 9 text

BLoC pattern layer design 9

Slide 10

Slide 10 text

BLoC pattern layer design https://medium.com/flutterpub/architecting-your-flutter-project-bd04e144a8f1 10

Slide 11

Slide 11 text

Guideline 1 1. BLoCͷೖग़ྗΠϯλʔϑΣʔε͸͢΂ͯ Stream/Sink Ͱ͋ Δ 2. BLoCͷґଘ͸ඞͣ஫ೖՄೳͰɺ؀ڥʹґଘ͠ͳ͍ 3. BLoC಺ʹ؀ڥ͝ͱͷ৚݅෼ذ͸࣋ͨͳ͍ 4. Ҏ্ͷϧʔϧʹै͏ݶΓɺଞͷ࣮૷ΛͲ͏͢Δ͔͸໰Θͳ͍ 1 https://github.com/tenhobi/flashcards/issues/12#issuecomment-373922966 11

Slide 12

Slide 12 text

TL;DL • ϏδωεϩδοΫΛίϯϙʔωϯτπϦʔͱผͷ৔ॴʹஔ͘ • BLoCͷ֎෦΁ͷΠϯλʔϑΣʔε͸ Stream(Observable) 12

Slide 13

Slide 13 text

https://www.youtube.com/watch?v=RS36gBEp8OI 13

Slide 14

Slide 14 text

e.g. Dart class Bloc { final emailController = StreamController(); // Add data to stream get changeEmail => emailController.sink.add; // Retrieve data from stream get email => emailController.stream; } void main() { final bloc = Bloc(); bloc.email.listen((value) { print(value); }); bloc.changeEmail("NEW EMAIL"); } 14

Slide 15

Slide 15 text

͜Μ͚ͩ ! ※ ΠϝʔδΛ௫ΉͨΊͷٖࣅίʔυͰ͢ class Bloc { let input: Observer let output: Observable } 15

Slide 16

Slide 16 text

e.g. Swift final class TaskBloc { /// input let addTask = PublishRelay() /// output var tasks: Observable<[Task]> { return _tasks.asObservable() } private let _tasks = BehaviorRelay<[Task]>(value: []) private let disposeBag = DisposeBag() init() { addTask .withLatestFrom(tasks) { ($0, $1) } .map { [$0] + $1 } .bind(to: _tasks) .disposed(by: disposeBag) } } 16

Slide 17

Slide 17 text

e.g. Swift taskBlock.tasks .subscribe(onNext: { tasks in print(tasks) }) .disposed(by: disposeBag) addButton.rx.tap .throttle(0.5, latest: false, scheduler: ConcurrentMainScheduler.instance) .map { Task(name: "task_01") } .bind(to: taskBlock.addTask) .disposed(by: disposeBag) 17

Slide 18

Slide 18 text

Feature • BLoC͔Βͷσʔλͷऔಘ͸ Observable.subscribe • BLoC΁ͷσʔλͷૹ৴͸ Observer.next 18

Slide 19

Slide 19 text

Feature • Components(View)͸Stream͔Βड͚औΔɾStreamʹσʔλΛ௥Ճ͢Δ͚ͩ • simple • MVVM, Flux, Reduxͱಉ͡ 19

Slide 20

Slide 20 text

Pros • ࣗ༝ • ܰྔReduxతͳ • ଞͷBLoCΛड͚औΔ͜ͱ΋Մೳ • Streamͷ߹੒ʹΑΓදݱྗ͕ߴ͍ Cons • Rxґଘ • Gࣾ 20

Slide 21

Slide 21 text

and more.. 21

Slide 22

Slide 22 text

ෳ਺ίϯϙʔωϯτ͔ΒBLoCΛࢀর͍ͨ͠2 • ֤ίϯϙʔωϯτ͔ΒBLoCΛΠϯελϯεԽ͢Δͱঢ়ଶ͕ڞ༗ग़དྷͳ͍ • BLoCΛSingletonΠϯελϯεʹ͢Δ? ! 2 https://qiita.com/kabochapo/items/8738223894fb74f952d3 22

Slide 23

Slide 23 text

InheritedWidget 23

Slide 24

Slide 24 text

Flutter.widgets.InheritedWidget3 Base class for widgets that efficiently propagate information down the tree. To obtain the nearest instance of a particular type of inherited widget from a build context, use BuildContext.inheritFromWidgetOfExactType. 3 https://docs.flutter.io/flutter/widgets/InheritedWidget-class.html 24

Slide 25

Slide 25 text

InheritedWidget • Provider extends InheritedWidget • BLoCʹΞΫηε͍ͨ͠Widget͕௚઀ܨ͕ΔͷͰ͸ͳ͘ɺProviderΛܦ༝͢Δ 25

Slide 26

Slide 26 text

e.g. Flutter class BlocProvider extends InheritedWidget { BlocProvider({Key key, Widget child}) : super(key: key, child: child); Bloc get bloc => Bloc(); @override bool updateShouldNotify(_) => true; // BlocProviderʹैଐ͢ΔWidgetͰ͜ͷϝιουΛ࢖͑͹BlocProviderͷΠϯελϯε͕ಘΒΕ // ͦΕΛ࢖ͬͯBlocͷΠϯελϯε΋ಘΒΕΔ static BlocProvider of(BuildContext context) { return (context.inheritFromWidgetOfExactType(BlocProvider) as BlocProvider); } } 26

Slide 27

Slide 27 text

e.g. Swift TBD • context ͱ͍͏࢓૊Έ͕ͳ͍.. • ୳ࡧͰ͖Μ(ແཧ΍ΓͳΒ͍͚Δ͕) • BlocProvider͸ϚετͰ͸ͳ͍ͱࢥ͏ • SingletonͰྑ͍͔ͳ ! • σʔλ૚͸ΞϓϦݻ༗Ͱอ࣋͢ΔͳͲ 27

Slide 28

Slide 28 text

e.g. Swift ※ ΠϝʔδΛ௫ΉͨΊͷٖࣅίʔυͰ͢ final class BlocProvider { let block: T static func of(_ view: UIView) -> TaskBloc { // Ҿ਺view͔Βଐ͢Δ `BLoC` Λ୳ࡧ͢Δ fatalError("implement") } } 28

Slide 29

Slide 29 text

Conclusion • BLoCύλʔϯ͸ܰྔͳঢ়ଶ؅ཧͷख๏ • ߦ͖ண͘ઌ͸MVVM, Flux, ReduxͳͲͷύλʔϯʹۙࣅͯ͠ ͍͘ͱࢥ͏ 29

Slide 30

Slide 30 text

"ઃܭύλʔϯ͸࠶ݱੑͷ͋Δ໰୊ʹର͢Δڞ௨ͷղܾࡦ"4 "ઃܭʹۜͷ஄ؙ͸ͳ͍͕ɺ ༷ʑͳύλʔϯΛ஌͍ͬͯΔ͜ͱͰۜͷ໋த཰͸্͛ΒΕΔ" 4 iOSΞϓϦઃܭύλʔϯೖ໳: https://peaks.cc/books/iOS_architecture 30

Slide 31

Slide 31 text

֓೦Λ஌ͬͯɺख਺Λ૿΍͍ͯ͜͠͏ 31

Slide 32

Slide 32 text

Thanks 32

Slide 33

Slide 33 text

SeeAlso • https://qiita.com/kabochapo/items/8738223894fb74f952d3 • https://medium.com/flutter-jp/bloc-provider-70e869b11b2f 33