Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
riverpodを理解したい
Search
Sponsored
·
SiteGround - Reliable hosting with speed, security, and support you can count on.
→
tatsubee
October 26, 2023
Technology
200
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
riverpodを理解したい
tatsubee
October 26, 2023
More Decks by tatsubee
See All by tatsubee
マルチウィンドウ実践ガイド
shoryuyamamoto
0
290
Create Spatial Photo with ImagePresentationComponent
shoryuyamamoto
0
110
pixivのリアーキテクチャにおける The Composable Architecter活用
shoryuyamamoto
0
210
pixivアプリは変化する
shoryuyamamoto
0
1.2k
マルチウィンドウでアプリケーションの表現を拡張する
shoryuyamamoto
1
410
【After iOSDC LT Night〜ピクシブ×日経×タイミー〜】実装!Interactive Widgets
shoryuyamamoto
0
74
SwiftPM マルチモジュール構成への第一歩
shoryuyamamoto
0
3.3k
TCA with UIKit [TCAでわいわいLT会]
shoryuyamamoto
1
1.5k
Dart Macrosに願いを [YOUTRUST x ゆめみ Flutter LT会@渋谷 #4]
shoryuyamamoto
0
900
Other Decks in Technology
See All in Technology
AIチャットの改善から見えた、良いAI体験とは / What Constitutes a Good AI Experience: Insights from Improving AI Chat
kubode
0
130
組織における AI-DLC 実践
askul
0
140
Oracle Cloud Infrastructure:2026年6月度サービス・アップデート
oracle4engineer
PRO
1
370
AIに障害切り分けを全部やってもらった。 。 。 。
estie
0
250
AIAU_UMEMOGU_ninomiya_slide
ninomiya_ii
0
280
iOS アプリの「これって不具合ですか?」を AI に調べてもらう
miichan
0
150
螺旋型キャリアの生存戦略 / kinoko-conf2026
rakus_dev
1
1.2k
飲食店もAIで。レジ締めやハンディシステムをつくってる話 / Using AI for restaurant management
vtryo
0
200
AWS Security Hub CSPMの成功・失敗体験
cmusudakeisuke
0
580
AWS Security Agent といっしょに脅威モデリングをやってみよう
amarelo_n24
1
210
UIパーツの設計を「型」から読み解く 〜TSKaigiのセッションから得た学び〜
yud0uhu
0
100
ぼっちではじめた登壇が「51名」「241件」の発信に化けた
subroh0508
1
330
Featured
See All Featured
Why Mistakes Are the Best Teachers: Turning Failure into a Pathway for Growth
auna
0
170
Agile that works and the tools we love
rasmusluckow
331
22k
Future Trends and Review - Lecture 12 - Web Technologies (1019888BNR)
signer
PRO
0
3.6k
We Analyzed 250 Million AI Search Results: Here's What I Found
joshbly
1
1.4k
Statistics for Hackers
jakevdp
799
230k
Designing for Performance
lara
611
70k
Building Adaptive Systems
keathley
44
3.1k
A Guide to Academic Writing Using Generative AI - A Workshop
ks91
PRO
1
340
Game over? The fight for quality and originality in the time of robots
wayneb77
1
210
The Curse of the Amulet
leimatthew05
2
13k
Become a Pro
speakerdeck
PRO
31
6k
Unsuck your backbone
ammeep
672
58k
Transcript
riverpodを理解したい pixiv Inc. tatsubee 2023.10.26
2 自己紹介 • 23新卒 • 福岡生まれ 福岡育ち 東京在住 • 最近やっていること
◦ お絵描き ◦ テニス ◦ iOS tatsubee iOSエンジニア
3 初めにちょっとだけ宣伝
4
5 福岡のFlutterコミュニティ 様々なイベントを開催して活発に活動中! • 月一でのLTイベント開催 • 先日の東京Flutterハッカソンへの参加 • その他内輪の勉強会 などなど
6 福岡のFlutterコミュニティ 様々なイベントを開催して活発に活動中!!! • 月一でのLTイベント開催 • 東京Flutterハッカソンへの参加 • その他内輪の勉強会 などなど
7 本題
8 riverpod勉強会 Fukuoka Flutter Fanclubで毎週やっている勉強会 目標: riverpodを「作れる」レベルのコード理解 ↓を順に、1時間でできる範囲でドキュメントやコードを読み進めていく • riverpodでできることの把握
• InheritedWidgetのコード理解 • providerのコード理解 • riverpodのコード理解
9 riverpod勉強会 Fukuoka Flutter Fanclubで毎週やっている勉強会 目標: riverpodを「作れる」レベルのコード理解 ↓を順に、1時間でできる範囲でドキュメントやコードを読み進めていく • riverpodでできることの把握
• InheritedWidgetのコード理解 ←ここまで進んだ • providerのコード理解 • riverpodのコード理解
10 このLTの内容 riverpod
11 このLTの内容 riverpod InheritedWidget
12 InheritedWidget 特徴 • 祖先のWidgetが管理する値にO(1)でアクセスできる • 値を購読する子孫のWidgetに、その値の変更を通知することができる (riverpodやproviderがあるので直接扱う必要性はない)
class Parent extends StatefulWidget { … } class _ParentState extends
State<Parent> { int count = 0; @override Widget build(BuildContext context) { return CountInherited( count: count, child: Scaffold( body: const Center( child: Child(), ), floatingActionButton: FloatingActionButton( onPressed: () => setState(() { count++; }), ), ), ); } } 13 InheritedWidget
class Parent extends StatefulWidget { … } class _ParentState extends
State<Parent> { int count = 0; @override Widget build(BuildContext context) { return CountInherited( count: count, child: Scaffold( body: const Center( child: Child(), ), floatingActionButton: FloatingActionButton( onPressed: () => setState(() { count++; }), ), ), ); } } 14 InheritedWidget class Child extends StatelessWidget { const Child({super.key}); @override Widget build(BuildContext context) => Text('${CountInherited.of(context).count}'); }
class Parent extends StatefulWidget { … } class _ParentState extends
State<Parent> { int count = 0; @override Widget build(BuildContext context) { return CountInherited( count: count, child: Scaffold( body: const Center( child: Child(), ), floatingActionButton: FloatingActionButton( onPressed: () => setState(() { count++; }), ), ), ); } } 15 InheritedWidget class CountInherited extends InheritedWidget { const CountInherited({ super.key, required this.count, required super.child, }); final int count; static CountInherited of(BuildContext context) => context.dependOnInheritedWidgetOfExactType()!; @override bool updateShouldNotify(CountInherited oldWidget) => oldWidget.count != count; }
class Parent extends StatefulWidget { … } class _ParentState extends
State<Parent> { int count = 0; @override Widget build(BuildContext context) { return CountInherited( count: count, child: Scaffold( body: const Center( child: Child(), ), floatingActionButton: FloatingActionButton( onPressed: () => setState(() { count++; }), ), ), ); } } 16 InheritedWidget
class Parent extends StatefulWidget { … } class _ParentState extends
State<Parent> { int count = 0; @override Widget build(BuildContext context) { return CountInherited( count: count, child: Scaffold( body: const Center( child: Child(), ), floatingActionButton: FloatingActionButton( onPressed: () => setState(() { count++; }), ), ), ); } } 17 InheritedWidget
class Parent extends StatefulWidget { … } class _ParentState extends
State<Parent> { int count = 0; @override Widget build(BuildContext context) { return CountInherited( count: count, child: Scaffold( body: const Center( child: Child(), ), floatingActionButton: FloatingActionButton( onPressed: () => setState(() { count++; }), ), ), ); } } 18 InheritedWidget
class Parent extends StatefulWidget { … } class _ParentState extends
State<Parent> { int count = 0; @override Widget build(BuildContext context) { return CountInherited( count: count, child: Scaffold( body: const Center( child: Child(), ), floatingActionButton: FloatingActionButton( onPressed: () => setState(() { count++; }), ), ), ); } } 19 InheritedWidget
20 InheritedWidgetの 中身を覗いてみる
abstract class InheritedWidget extends ProxyWidget { const InheritedWidget({ super.key, required
super.child }); @override InheritedElement createElement() => InheritedElement(this); @protected bool updateShouldNotify(covariant InheritedWidget oldWidget); } 21 InheritedElementの作成と 変更の通知の判定のみ!
class InheritedElement extends ProxyElement { InheritedElement(InheritedWidget super.widget); final Map<Element, Object?>
_dependents = HashMap<Element, Object?>(); @override void _updateInheritance() {...} @override void debugDeactivated() {...} @protected Object? getDependencies(Element dependent) {...} @protected void updateDependencies(Element dependent, Object? aspect) {...} @protected void notifyDependent(covariant InheritedWidget oldWidget, Element dependent) {...} @override void updated(InheritedWidget oldWidget) {...} @override void notifyClients(InheritedWidget oldWidget) {...} } 22
23 O(1)でアクセスする仕組み
24 アクセス方法
abstract class Element extends DiagnosticableTree implements BuildContext { PersistentHashMap<Type, InheritedElement>?
_inheritedElements; @override T? dependOnInheritedWidgetOfExactType<T extends InheritedWidget>({ Object? aspect }) { final InheritedElement? ancestor = _inheritedElements == null ? null : _inheritedElements![T]; if (ancestor != null) { return dependOnInheritedElement(ancestor, aspect: aspect) as T; } _hadUnsatisfiedDependencies = true; return null; } } 25 = watch
abstract class Element extends DiagnosticableTree implements BuildContext { PersistentHashMap<Type, InheritedElement>?
_inheritedElements; @override T? dependOnInheritedWidgetOfExactType<T extends InheritedWidget>({ Object? aspect }) { final InheritedElement? ancestor = _inheritedElements == null ? null : _inheritedElements![T]; if (ancestor != null) { return dependOnInheritedElement(ancestor, aspect: aspect) as T; } _hadUnsatisfiedDependencies = true; return null; } } 26 自身が持っている_inheritedElements の中から 型が一致するInheritedElementを返す = watch
27 _inheritedElementsへの格納
abstract class Element extends DiagnosticableTree implements BuildContext { @mustCallSuper void
mount(Element? parent, Object? newSlot) { _updateInheritance(); } } 28
abstract class Element extends DiagnosticableTree implements BuildContext { void _updateInheritance()
{ _inheritedElements = _parent?._inheritedElements; } } class InheritedElement extends ProxyElement { @override void _updateInheritance() { final PersistentHashMap<Type, InheritedElement> incomingWidgets = _parent?._inheritedElements ?? const PersistentHashMap<Type, InheritedElement>.empty(); _inheritedElements = incomingWidgets.put(widget.runtimeType, this); } } 29
abstract class Element extends DiagnosticableTree implements BuildContext { void _updateInheritance()
{ _inheritedElements = _parent?._inheritedElements; } } class InheritedElement extends ProxyElement { @override void _updateInheritance() { final PersistentHashMap<Type, InheritedElement> incomingWidgets = _parent?._inheritedElements ?? const PersistentHashMap<Type, InheritedElement>.empty(); _inheritedElements = incomingWidgets.put(widget.runtimeType, this); } } 30 親の_inheritedElenentsを そのまま引き継ぐ
abstract class Element extends DiagnosticableTree implements BuildContext { void _updateInheritance()
{ _inheritedElements = _parent?._inheritedElements; } } class InheritedElement extends ProxyElement { @override void _updateInheritance() { final PersistentHashMap<Type, InheritedElement> incomingWidgets = _parent?._inheritedElements ?? const PersistentHashMap<Type, InheritedElement>.empty(); _inheritedElements = incomingWidgets.put(widget.runtimeType, this); } } 31 親から引き継いだ _inheritedElenentsに 自身を挿入する
32 視覚的に見てみると...
33 Parent CounterInherited Child Widgetツリー { } { CounterInherited: InheritedElement
} _inheritedElements { CounterInherited: InheritedElement }
34 Parent CounterInherited Child Widgetツリー { } { CounterInherited: InheritedElement
} _inheritedElements { CounterInherited: InheritedElement } アクセス
35 変更を通知する仕組み
36 countの値を変更する時
class Parent extends StatefulWidget { … } class _ParentState extends
State<Parent> { int count = 0; @override Widget build(BuildContext context) { return CountInherited( count: count, child: Scaffold( body: const Center( child: Child(), ), floatingActionButton: FloatingActionButton( onPressed: () => setState(() { count++; }), ), ), ); } } 37
class Parent extends StatefulWidget { … } class _ParentState extends
State<Parent> { int count = 0; @override Widget build(BuildContext context) { return CountInherited( count: count, child: Scaffold( body: const Center( child: Child(), ), floatingActionButton: FloatingActionButton( onPressed: () => setState(() { count++; }), ), ), ); } } 38 リビルド範囲
class Parent extends StatefulWidget { … } class _ParentState extends
State<Parent> { int count = 0; @override Widget build(BuildContext context) { return CountInherited( count: count, child: Scaffold( body: const Center( child: Child(), ), floatingActionButton: FloatingActionButton( onPressed: () => setState(() { count++; }), ), ), ); } } 39 リビルド範囲
class Parent extends StatefulWidget { … } class _ParentState extends
State<Parent> { int count = 0; @override Widget build(BuildContext context) { return CountInherited( count: count, child: Scaffold( body: const Center( child: Child(), ), floatingActionButton: FloatingActionButton( onPressed: () => setState(() { count++; }), ), ), ); } } 40 リビルド範囲 リビルドされない constによってリビルドが抑 制される
class Child extends StatelessWidget { const Child({super.key}); @override Widget build(BuildContext
context) => Text('${CountInherited.of(context).count}'); } 41
class Child extends StatelessWidget { const Child({super.key}); @override Widget build(BuildContext
context) => Text('${CountInherited.of(context).count}'); } 42 StatefulWidgetの方が わかりやすいので変換
class Child extends StatefulWidget { … } class _ChildState extends
State<Child> { @override void didChangeDependencies() { … } @override Widget build(BuildContext context) { final countInherited = context.dependOnInheritedWidgetOfExactType()! as CountInherited; return Text('${countInherited.count}); } } 43 StatefulWidgetの方が わかりやすいので変換
class Child extends StatefulWidget { … } class _ChildState extends
State<Child> { @override void didChangeDependencies() { … } @override Widget build(BuildContext context) { final countInherited = context.dependOnInheritedWidgetOfExactType()! as CountInherited; return Text('${countInherited.count}); } } 44 setStateされると didChangeDependencies が発火!
class Child extends StatefulWidget { … } class _ChildState extends
State<Child> { @override void didChangeDependencies() { … } @override Widget build(BuildContext context) { final countInherited = context.dependOnInheritedWidgetOfExactType()! as CountInherited; return Text('${countInherited.count}); } } 45 ”Dependencies”とは、 InheritedWidgetのこと!
46 時間がなさそうなのでここまで! 気になる方は懇親会で!
class InheritedElement extends ProxyElement { InheritedElement(InheritedWidget super.widget); final Map<Element, Object?>
_dependents = HashMap<Element, Object?>(); @override void _updateInheritance() {...} @override void debugDeactivated() {...} @protected Object? getDependencies(Element dependent) {...} @protected void updateDependencies(Element dependent, Object? aspect) {...} @protected void notifyDependent(covariant InheritedWidget oldWidget, Element dependent) {...} @override void updated(InheritedWidget oldWidget) {...} @override void notifyClients(InheritedWidget oldWidget) {...} } 47
class InheritedElement extends ProxyElement { InheritedElement(InheritedWidget super.widget); final Map<Element, Object?>
_dependents = HashMap<Element, Object?>(); @override void _updateInheritance() {...} @override void debugDeactivated() {...} @protected Object? getDependencies(Element dependent) {...} @protected void updateDependencies(Element dependent, Object? aspect) {...} @protected void notifyDependent(covariant InheritedWidget oldWidget, Element dependent) {...} @override void updated(InheritedWidget oldWidget) {...} @override void notifyClients(InheritedWidget oldWidget) {...} } 48 Log setState ParentWidget.build InheritedElement.updated InheritedWidget.updateShouldNotify:true InheritedWidget.updateShouldNotify:true InheritedElement.notifyClients InheritedElement.notifyDependent ChildWidget.didChangeDependencies ChildWidget.build InheritedElement.updateDependencies InheritedElement.setDependencies
49 ありがとうございました!
50 魂だけでも福岡に送ってみませんか? Discordサーバー