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
tatsubee
October 26, 2023
Technology
210
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
320
Create Spatial Photo with ImagePresentationComponent
shoryuyamamoto
0
110
pixivのリアーキテクチャにおける The Composable Architecter活用
shoryuyamamoto
0
210
pixivアプリは変化する
shoryuyamamoto
0
1.2k
マルチウィンドウでアプリケーションの表現を拡張する
shoryuyamamoto
1
430
【After iOSDC LT Night〜ピクシブ×日経×タイミー〜】実装!Interactive Widgets
shoryuyamamoto
0
80
SwiftPM マルチモジュール構成への第一歩
shoryuyamamoto
0
3.3k
TCA with UIKit [TCAでわいわいLT会]
shoryuyamamoto
1
1.5k
Dart Macrosに願いを [YOUTRUST x ゆめみ Flutter LT会@渋谷 #4]
shoryuyamamoto
0
910
Other Decks in Technology
See All in Technology
JavaScript 研修 (2026)
recruitengineers
PRO
2
530
【Google Cloud Next Tokyo'26】Gemini Enterprise と Oracle AI Database で実現する、業務データ活用を実現する AI エージェント実装
shisyu_gaku
0
250
Digitization部 紹介資料
sansan33
PRO
2
7.7k
TypeScript入門 2026
recruitengineers
PRO
3
570
AIエージェントを前提としたプラットフォーム エンジニアリング:GKEで作るAgent-Ready Golden Path
legalontechnologies
PRO
2
230
FORENSIA: ローカルLLMフォレンジックハーネス
sumeshi
2
380
[ChatGPT Work LT]事務作業が苦手な人のための バックオフィスの「半」自動化
chimaki_iot
0
280
オートロックマンションなのに、各部屋は施錠なし!? 攻撃者が組織内ネットワークで大暴れする理由 / The Front Door Is Locked, but the Rooms Are Wide Open: Why Attackers Move Freely Inside Enterprise Networks
nttcom
1
1.7k
ホームラボ紹介
y_sera15
0
160
Flutterをカメラで動かしたかった話
sony
1
140
グローバル基準のSREは、運用現場でどう機能したか:成熟度アセスメントの実践 / SRE NEXT 2026
sorawatanabe
0
210
え?フロントエンドエンジニアの ワイがインフラも!?
puku0x
1
550
Featured
See All Featured
How to Talk to Developers About Accessibility
jct
2
510
Helping Users Find Their Own Way: Creating Modern Search Experiences
danielanewman
31
3.3k
Connecting the Dots Between Site Speed, User Experience & Your Business [WebExpo 2025]
tammyeverts
11
990
The Curious Case for Waylosing
cassininazir
1
450
AI in Enterprises - Java and Open Source to the Rescue
ivargrimstad
0
1.4k
Ecommerce SEO: The Keys for Success Now & Beyond - #SERPConf2024
aleyda
1
2.1k
Unlocking the hidden potential of vector embeddings in international SEO
frankvandijk
0
890
Six Lessons from altMBA
skipperchong
29
4.4k
Believing is Seeing
oripsolob
1
190
How to build an LLM SEO readiness audit: a practical framework
nmsamuel
1
860
Visualizing Your Data: Incorporating Mongo into Loggly Infrastructure
mongodb
49
10k
The Director’s Chair: Orchestrating AI for Truly Effective Learning
tmiket
1
260
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サーバー