2018/07/19
Flutter Meetup Tokyo #3
new TextField(
controller: _controller,
decoration: new InputDecoration(hintText: 'Type word'),
onSubmitted: (String inputValue) {
if (inputValue.isEmpty) {
return;
}
final String query = inputValue.toLowerCase();
this.fetchSentences(query).then((_list) {
setState(() {
_searchResults = _list;
});
});
}
)
setState で反映された値で ListView を生成
new Expanded(
child: new ListView(
children: ListTile.divideTiles(
context: context,
tiles: _searchResults.map(
(SearchResult searchResult) {
return new ListTile(
title: formatString(searchResult.word),
trailing: new Row(...
class SearchBloc {
// Inputs
final _query = new BehaviorSubject<String>();
Sink<String> get query => _query.sink;
// Outputs
Stream<List<SearchResult>> _results = Stream.empty();
Stream<List<SearchResult>> get results => _results;
SearchBloc() {
_results = _query
.distinct()
.switchMap((query) => new Observable.fromFuture(_search(query)))
.map(_xmlToSearchResults)
.asBroadcastStream();
}
...
}
入力値を Sink に渡すだけ
new Padding(
padding: const EdgeInsets.all(16.0),
child: new TextField(
controller: _controller,
decoration: new InputDecoration(hintText: 'Type word'),
onSubmitted: (String query) {
_searchBloc.query.add(query);
},
),
),
StreamBuilder<List<SearchResult>>(
stream: _searchBloc.results,
builder: (context, snapshot) {
return new ListView(
children: ListTile
.divideTiles(
context: context,
tiles: snapshot.data.map((SearchResult searchResult) {
return new ListTile(
title: _formatString(context, searchResult.word),
trailing: new Row(...
InheritedWidget パターンを使う
class SearchProvider extends InheritedWidget {
final SearchBloc searchBloc;
SearchProvider({Key key, SearchBloc searchBloc, Widget child})
: searchBloc = searchBloc ?? new SearchBloc(),
super(key: key, child: child);
@override
bool updateShouldNotify(InheritedWidget oldWidget) => true;
static SearchBloc of(BuildContext context) =>
(context.inheritFromWidgetOfExactType(SearchProvider) as SearchProvider)
.searchBloc;
}
3. 対象ウィジェットをラップ
ラップしたときに BLoC インスタンスを生成
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return SearchProvider(
searchBloc: SearchBloc(),
child: new MaterialApp(
title: 'Flutter Demo',
theme: new ThemeData(primarySwatch: Colors.pink),
home: new MyHomePage(title: 'Flutter Demo Home Page'),
)
);
}
}
4. build メソッドの中で of メソッド経由で
BLoC インスタンスを取得
class Search extends StatelessWidget {
@override
Widget build(BuildContext context) {
final _searchBloc = SearchProvider.of(context);
final _controller = new TextEditingController();
return new Column(
children: <Widget>[
new TextField(
controller: _controller,
decoration: new InputDecoration(hintText: 'Type word'),
onSubmitted: (String query) {
_searchBloc.query.add(query);
},
),
new Expanded(
child: StreamBuilder<List<SearchResult>>(
stream: _searchBloc.results,
builder: (context, snapshot) {
return new ListView(
children: ListTile
.divideTiles(
context: context,
tiles: snapshot.data.map((SearchResult searchResult) {
return new ListTile(
title: _formatString(context, searchResult.word),
trailing: new Row(...
Does Flutter come with a dependency injection framework or solution?
Not at this time. Please share your ideas at flutter-dev@googlegroups.com.
現状、Flutter には DI の仕組みは存在しない
あるにはある
けっこう、ある
どれ使おう??
公式ではないがある
がしかし Latest commit 4 months ago...
https://github.com/google/inject.dart
class Search extends StatelessWidget {
final SearchBloc _searchBloc;
Search(this._searchBloc);
@override
Widget build(BuildContext context) {
final _controller = new TextEditingController();
return new Column(
children: <Widget>[
new TextField(
controller: _controller,
decoration: new InputDecoration(hintText: 'Type word'),
onSubmitted: (String query) {
_searchBloc.query.add(query);
},
),
new Expanded(
child: StreamBuilder<List<SearchResult>>(
stream: _searchBloc.results,
builder: (context, snapshot) {
return new ListView(
children: ListTile
.divideTiles(
context: context,
tiles: snapshot.data.map((SearchResult searchResult) {
return new ListTile(
title: _formatString(context, searchResult.word),
trailing: new Row(...
import 'package:flutter/material.dart';
import 'package:flutter_simple_dependency_injection/injector.dart';
import 'package:doughnut/search/search.dart';
import 'package:doughnut/search/search_bloc.dart';
void main() {
final injector = Injector.getInjector();
injector.map<SearchBloc>((i) => new SearchBloc(), isSingleton: true);
injector.map<Search>((i) => new Search(injector.get<SearchBloc>()));
runApp(new MyApp());
}
@override
Widget build(BuildContext context) {
final injector = Injector.getInjector();
return new Scaffold(
appBar: new AppBar(
title: new Text('doughnut'),
actions: <Widget>[
new IconButton(
icon: new Icon(Icons.info),
onPressed: () {
...
})
]
),
body: injector.get<Search>(),
...