Creating test database for alias 'default'...
System check identified no issues (0 silenced).
.
----------------------------------------------------------------------
Ran 1 test in 0.410s
OK
Destroying test database for alias 'default'...
Creating test database for alias 'default'...
System check identified no issues (0 silenced).
F
======================================================================
FAIL: test_create_report (report.tests.ReportTests)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/xxx/report/tests.py", line 40, in test_create_report
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
AssertionError: 200 != 201
----------------------------------------------------------------------
Ran 1 test in 0.411s
FAILED (failures=1)
Destroying test database for alias 'default'...
import 'package:example/my_state_notifier.dart';
import 'package:flutter/material.dart';
import 'package:flutter_state_notifier/flutter_state_notifier.dart';
import 'package:provider/provider.dart';
// This is the default counter example reimplemented using StateNotifier + provider// It will print in the console the counter whenever it changes// The state change is also animated.// The "print to console" feature is abstracted through a "Logger" class like// we would do in production.// This showcase how our custom MyStateNotifier does not depend on Flutter,// but is still able to read providers and be used as usual in a Flutter app.void main() {
runApp(
MultiProvider(
providers: [
Provider<Logger>(create: (_) => ConsoleLogger()),
StateNotifierProvider<MyStateNotifier, MyState>(
create: (_) => MyStateNotifier(),
// Override MyState to make it animated
builder: (context, child) {
return TweenAnimationBuilder<MyState>(
duration:constDuration(milliseconds:500),
tween: MyStateTween(end: context.watch<MyState>()),
builder: (context, state, _) {
return Provider.value(value: state, child: child);
},
);
},
),
],
child: MyApp(),
),
);
}
/// A [MyStateTween].////// This will apply an [IntTween] on [MyState.count].class MyStateTween extends Tween<MyState> {
MyStateTween({MyState begin, MyState end}) :super(begin: begin, end: end);
@override
MyState lerp(double t) {
final countTween = IntTween(begin: begin.count, end: end.count);
// Tween the countreturn MyState(
countTween.lerp(t),
);
}
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
returnconst MaterialApp(
title:'Flutter Demo',
home: MyHomePage(),
);
}
}
class MyHomePage extends StatelessWidget {
const MyHomePage({Key key}) :super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title:const Text('Counter example'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children:<Widget>[
const Text(
'You have pushed the button this many times:',
),
Text(
context.select((MyState value) => value.count).toString(),
style: Theme.of(context).textTheme.headline4,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: context.watch<MyStateNotifier>().increment,
tooltip:'Increment',
child: Icon(Icons.add),
),
);
}
}
Reduxは、「Single source of truth」、「State is read only」、「Changes are made with pure function」の3つの原則によってよりわかりやすく安全に状態変数を扱うためのアーキテクチャ です。以下の図のような要素・フローによってこれらの原則が実現されます(正確には、原則を守りやすくなるということだと思います)。また、Fluxに見られる「単一方向の状態変更フロー」も満たすことができます。
import 'package:flutter/material.dart';
import 'package:flutter_redux/flutter_redux.dart';
import 'package:redux/redux.dart';
// One simple action: Increment
enum Actions { Increment }
// The reducer, which takes the previous count and increments it in response// to an Increment action.int counterReducer(int state, dynamic action) {
if (action == Actions.Increment) {
return state +1;
}
return state;
}
void main() {
// Create your store as a final variable in a base Widget. This works better// with Hot Reload than creating it directly in the `build` function.final store = new Store<int>(counterReducer, initialState:0);
runApp(new FlutterReduxApp(
title:'Flutter Redux Demo',
store: store,
));
}
class FlutterReduxApp extends StatelessWidget {
final Store<int> store;
finalString title;
FlutterReduxApp({Key key, this.store, this.title}) :super(key: key);
@override
Widget build(BuildContext context) {
// The StoreProvider should wrap your MaterialApp or WidgetsApp. This will// ensure all routes have access to the store.returnnew StoreProvider<int>(
// Pass the store to the StoreProvider. Any ancestor `StoreConnector`// Widgets will find and use this value as the `Store`.
store: store,
child:new MaterialApp(
theme:new ThemeData.dark(),
title: title,
home:new Scaffold(
appBar:new AppBar(
title:new Text(title),
),
body:new Center(
child:new Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
new Text(
'You have pushed the button this many times:',
),
// Connect the Store to a Text Widget that renders the current// count.//// We'll wrap the Text Widget in a `StoreConnector` Widget. The// `StoreConnector` will find the `Store` from the nearest// `StoreProvider` ancestor, convert it into a String of the// latest count, and pass that String to the `builder` function// as the `count`.//// Every time the button is tapped, an action is dispatched and// run through the reducer. After the reducer updates the state,// the Widget will be automatically rebuilt with the latest// count. No need to manually manage subscriptions or Streams!new StoreConnector<int, String>(
converter: (store) => store.state.toString(),
builder: (context, count) {
returnnew Text(
count,
style: Theme.of(context).textTheme.display1,
);
},
)
],
),
),
// Connect the Store to a FloatingActionButton. In this case, we'll// use the Store to build a callback that with dispatch an Increment// Action.//// Then, we'll pass this callback to the button's `onPressed` handler.
floatingActionButton:new StoreConnector<int, VoidCallback>(
converter: (store) {
// Return a `VoidCallback`, which is a fancy name for a function// with no parameters. It only dispatches an Increment action.return () => store.dispatch(Actions.Increment);
},
builder: (context, callback) {
returnnew FloatingActionButton(
// Attach the `callback` to the `onPressed` attribute
onPressed: callback,
tooltip:'Increment',
child:new Icon(Icons.add),
);
},
),
),
),
);
}
}
$ webdev serve --hot-reload
Creating build script, took 7010ms
[INFO] Setting up file watchers completed, took 10ms
[INFO] Waiting for all file watchers to be ready completed, took 201ms
[INFO] Building new asset graph completed, took 1.0s
[INFO] Checking for unexpected pre-existing outputs. completed, took 1ms
[INFO] Running build completed, took 25.8s
[INFO] Caching finalized dependency graph completed, took 184ms
[INFO] Succeeded after 26.0s with 571 outputs (3248 actions)
Serving `web` on http://localhost:8080
$ webdev serve --hot-reload
webdev could not run for this project.
The `build_web_compilers` version – 2.2.3 – is not within the allowed constraint – >=0.3.6 <2.0.0.
エラーに記載のバージョンが同じものを探そうとすると、以下のようなサイト(何語?)を参考にしないといけないあたり、Flutter for webの未熟さ具合が感じられます。