Skip to content

Commit e75b68b

Browse files
committed
Add bloc_library example
1 parent f5acaa5 commit e75b68b

File tree

100 files changed

+3088
-9
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

100 files changed

+3088
-9
lines changed

.travis.yml

+18-8
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
jobs:
22
include:
3-
3+
44
- stage: Unit Testing
55
language: generic
66
os: linux
77
env: All unit and widget tests
88
before_script:
99
- sudo apt-get install -y --no-install-recommends lib32stdc++6 libstdc++6 > /dev/null
1010

11-
# - git clone https://github.com/flutter/flutter.git -b stable
12-
# - flutter precache
11+
# - git clone https://github.com/flutter/flutter.git -b stable
12+
# - flutter precache
1313

1414
# install pre-compiled flutter
1515
- FLUTTER_CHANNEL=stable
@@ -61,8 +61,8 @@ jobs:
6161
- echo no | avdmanager create avd --force -n test -k "system-images;android-$EMULATOR_API_LEVEL;$ANDROID_ABI"
6262
- $ANDROID_HOME/emulator/emulator -avd test -no-audio -no-window -gpu swiftshader &
6363

64-
# - git clone https://github.com/flutter/flutter.git -b stable
65-
# - flutter precache
64+
# - git clone https://github.com/flutter/flutter.git -b stable
65+
# - flutter precache
6666

6767
# install pre-compiled flutter
6868
- FLUTTER_CHANNEL=stable
@@ -92,15 +92,15 @@ jobs:
9292
- open /Applications/Xcode.app/Contents/Developer/Applications/Simulator.app
9393
# skip homebrew update
9494
- export HOMEBREW_NO_AUTO_UPDATE=1
95-
# - brew update
95+
# - brew update
9696
- brew install libimobiledevice
9797
- brew install ideviceinstaller
9898
- brew install ios-deploy
9999
- brew install cocoapods || echo 'ignore exit(1)'
100100
- brew link --overwrite cocoapods
101101

102-
# - git clone https://github.com/flutter/flutter.git -b stable
103-
# - flutter precache
102+
# - git clone https://github.com/flutter/flutter.git -b stable
103+
# - flutter precache
104104

105105
# install pre-compiled flutter
106106
- FLUTTER_CHANNEL=stable
@@ -125,6 +125,16 @@ jobs:
125125
env: built_redux_ios
126126
before_install: *before_install_osx
127127
script: travis_retry ./scripts/ci.sh ./built_redux
128+
- <<: *integration-test-staging
129+
os: linux
130+
env: bloc_library_android
131+
script: travis_retry ./scripts/ci.sh ./bloc_library
132+
- <<: *integration-test-staging
133+
os: osx
134+
osx_image: xcode8.0
135+
env: bloc_library_ios
136+
before_install: *before_install_osx
137+
script: travis_retry ./scripts/ci.sh ./bloc_library
128138
- <<: *integration-test-staging
129139
os: linux
130140
env: firestore_redux_android

bloc_library/.gitignore

+71
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
# Miscellaneous
2+
*.class
3+
*.lock
4+
*.log
5+
*.pyc
6+
*.swp
7+
.DS_Store
8+
.atom/
9+
.buildlog/
10+
.history
11+
.svn/
12+
13+
# IntelliJ related
14+
*.iml
15+
*.ipr
16+
*.iws
17+
.idea/
18+
19+
# Visual Studio Code related
20+
.vscode/
21+
22+
# Flutter/Dart/Pub related
23+
**/doc/api/
24+
.dart_tool/
25+
.flutter-plugins
26+
.packages
27+
.pub-cache/
28+
.pub/
29+
build/
30+
31+
# Android related
32+
**/android/**/gradle-wrapper.jar
33+
**/android/.gradle
34+
**/android/captures/
35+
**/android/gradlew
36+
**/android/gradlew.bat
37+
**/android/local.properties
38+
**/android/**/GeneratedPluginRegistrant.java
39+
40+
# iOS/XCode related
41+
**/ios/**/*.mode1v3
42+
**/ios/**/*.mode2v3
43+
**/ios/**/*.moved-aside
44+
**/ios/**/*.pbxuser
45+
**/ios/**/*.perspectivev3
46+
**/ios/**/*sync/
47+
**/ios/**/.sconsign.dblite
48+
**/ios/**/.tags*
49+
**/ios/**/.vagrant/
50+
**/ios/**/DerivedData/
51+
**/ios/**/Icon?
52+
**/ios/**/Pods/
53+
**/ios/**/.symlinks/
54+
**/ios/**/profile
55+
**/ios/**/xcuserdata
56+
**/ios/.generated/
57+
**/ios/Flutter/App.framework
58+
**/ios/Flutter/Flutter.framework
59+
**/ios/Flutter/Generated.xcconfig
60+
**/ios/Flutter/app.flx
61+
**/ios/Flutter/app.zip
62+
**/ios/Flutter/flutter_assets/
63+
**/ios/ServiceDefinitions.json
64+
**/ios/Runner/GeneratedPluginRegistrant.*
65+
66+
# Exceptions to above rules.
67+
!**/ios/**/default.mode1v3
68+
!**/ios/**/default.mode2v3
69+
!**/ios/**/default.pbxuser
70+
!**/ios/**/default.perspectivev3
71+
!/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages

bloc_library/.metadata

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# This file tracks properties of this Flutter project.
2+
# Used by Flutter tool to assess capabilities and perform upgrades etc.
3+
#
4+
# This file should be version controlled and should not be manually edited.
5+
6+
version:
7+
revision: 5391447fae6209bb21a89e6a5a6583cac1af9b4b
8+
channel: beta
9+
10+
project_type: app

bloc_library/README.md

+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
# bloc_library sample
2+
3+
This sample makes use of the [bloc](https://pub.dartlang.org/packages/bloc) and [flutter_bloc](https://pub.dartlang.org/packages/flutter_bloc) libraries to manage state.
4+
5+
Check out the [bloc library documentation](https://felangel.github.io/bloc) for more details and tutorials.
6+
7+
## Key Concepts
8+
9+
* Lift State Up
10+
* If a bloc is needed by multiple widgets provide it using `BlocProvider` at the greatest common ancestor
11+
* `Events` are the input to a bloc.
12+
* They are commonly dispatched in response to user interactions such as button presses or lifecycle events like page loads.
13+
* `States` are the output of a bloc and represent a part of your application's state.
14+
* components can be notified of states and redraw portions of themselves based on the current state.
15+
* The change from one state to another is called a `Transition`.
16+
* A `Transition` consists of the current state, the event, and the next state.
17+
* A bloc converts a `Stream` of incoming `Events` into a `Stream` of outgoing `States`
18+
19+
## Updating App State
20+
21+
Every bloc has a `dispatch` method. `Dispatch` takes an event and triggers `mapEventToState`. Dispatch notifies the bloc of a new event which will then trigger a state change.
22+
23+
## Sharing Data between Blocs
24+
25+
In this implementation, the `FilteredTodosBloc` depends on the `TodosBloc` and will update the list of filtered todos in response to changes in the `TodosBloc`.
26+
This approach demonstrates how we can build a reactive application by composing blocs from other blocs. On app start, the `TodosBloc` is hydrated with todos from the repository and from that moment forward, all mutations to todos are executed through the `TodosBloc` which persists the changes asynchronously. The `FilteredTodosBloc` listens for changes in the `TodosBloc` state and will update it's list of filtered todos. The result is, a hierarchy of states with all todos being managed by the `TodosBloc` and a subset of those todos (filtered todos) being managed by the `FilteredTodosBloc`.
27+
28+
## Updating UI
29+
30+
`BlocBuilder` is a Flutter widget which requires a bloc and a builder function. `BlocBuilder` handles building the widget in response to new states. `BlocBuilder` is very similar to `StreamBuilder` but has a simplified API to reduce the amount of boilerplate code needed and is also optimized to avoid unnecessary rebuilds.
31+
32+
## Testing
33+
34+
Generally, this app conforms the "Testing Pyramid": Lots of Unit tests, fewer Widget tests, and fewer integration tests.
35+
36+
* Unit tests
37+
- `Blocs` can easily be tested by mocking dependencies with `Mockito`. `Events` can be dispatched and we can assert that the blocs' state has changed correctly.
38+
* Widget Tests
39+
- Widgets can be tested by passing in fake data and making assertions against the Widget rendered with that data.
40+
* Integration Tests
41+
- Run the app and drive it using flutter_driver `flutter drive --target test_driver/todo_app.dart`.
42+

bloc_library/android/.project

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<projectDescription>
3+
<name>android</name>
4+
<comment>Project android created by Buildship.</comment>
5+
<projects>
6+
</projects>
7+
<buildSpec>
8+
<buildCommand>
9+
<name>org.eclipse.buildship.core.gradleprojectbuilder</name>
10+
<arguments>
11+
</arguments>
12+
</buildCommand>
13+
</buildSpec>
14+
<natures>
15+
<nature>org.eclipse.buildship.core.gradleprojectnature</nature>
16+
</natures>
17+
</projectDescription>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
connection.project.dir=
2+
eclipse.preferences.version=1

bloc_library/android/app/.classpath

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<classpath>
3+
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8/"/>
4+
<classpathentry kind="con" path="org.eclipse.buildship.core.gradleclasspathcontainer"/>
5+
<classpathentry kind="output" path="bin/default"/>
6+
</classpath>

bloc_library/android/app/.project

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<projectDescription>
3+
<name>app</name>
4+
<comment>Project app created by Buildship.</comment>
5+
<projects>
6+
</projects>
7+
<buildSpec>
8+
<buildCommand>
9+
<name>org.eclipse.jdt.core.javabuilder</name>
10+
<arguments>
11+
</arguments>
12+
</buildCommand>
13+
<buildCommand>
14+
<name>org.eclipse.buildship.core.gradleprojectbuilder</name>
15+
<arguments>
16+
</arguments>
17+
</buildCommand>
18+
</buildSpec>
19+
<natures>
20+
<nature>org.eclipse.jdt.core.javanature</nature>
21+
<nature>org.eclipse.buildship.core.gradleprojectnature</nature>
22+
</natures>
23+
</projectDescription>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
connection.project.dir=..
2+
eclipse.preferences.version=1

bloc_library/android/app/build.gradle

+61
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
def localProperties = new Properties()
2+
def localPropertiesFile = rootProject.file('local.properties')
3+
if (localPropertiesFile.exists()) {
4+
localPropertiesFile.withReader('UTF-8') { reader ->
5+
localProperties.load(reader)
6+
}
7+
}
8+
9+
def flutterRoot = localProperties.getProperty('flutter.sdk')
10+
if (flutterRoot == null) {
11+
throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
12+
}
13+
14+
def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
15+
if (flutterVersionCode == null) {
16+
flutterVersionCode = '1'
17+
}
18+
19+
def flutterVersionName = localProperties.getProperty('flutter.versionName')
20+
if (flutterVersionName == null) {
21+
flutterVersionName = '1.0'
22+
}
23+
24+
apply plugin: 'com.android.application'
25+
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
26+
27+
android {
28+
compileSdkVersion 27
29+
30+
lintOptions {
31+
disable 'InvalidPackage'
32+
}
33+
34+
defaultConfig {
35+
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
36+
applicationId "com.example.flutterbloc"
37+
minSdkVersion 16
38+
targetSdkVersion 27
39+
versionCode flutterVersionCode.toInteger()
40+
versionName flutterVersionName
41+
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
42+
}
43+
44+
buildTypes {
45+
release {
46+
// TODO: Add your own signing config for the release build.
47+
// Signing with the debug keys for now, so `flutter run --release` works.
48+
signingConfig signingConfigs.debug
49+
}
50+
}
51+
}
52+
53+
flutter {
54+
source '../..'
55+
}
56+
57+
dependencies {
58+
testImplementation 'junit:junit:4.12'
59+
androidTestImplementation 'com.android.support.test:runner:1.0.2'
60+
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
61+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
2+
package="com.example.flutterbloc">
3+
4+
<!-- The INTERNET permission is required for development. Specifically,
5+
flutter needs it to communicate with the running application
6+
to allow setting breakpoints, to provide hot reload, etc.
7+
-->
8+
<uses-permission android:name="android.permission.INTERNET"/>
9+
10+
<!-- io.flutter.app.FlutterApplication is an android.app.Application that
11+
calls FlutterMain.startInitialization(this); in its onCreate method.
12+
In most cases you can leave this as-is, but you if you want to provide
13+
additional functionality it is fine to subclass or reimplement
14+
FlutterApplication and put your custom class here. -->
15+
<application
16+
android:name="io.flutter.app.FlutterApplication"
17+
android:label="bloc_library"
18+
android:icon="@mipmap/ic_launcher">
19+
<activity
20+
android:name=".MainActivity"
21+
android:launchMode="singleTop"
22+
android:theme="@style/LaunchTheme"
23+
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale|screenLayout|density"
24+
android:hardwareAccelerated="true"
25+
android:windowSoftInputMode="adjustResize">
26+
<!-- This keeps the window background of the activity showing
27+
until Flutter renders its first frame. It can be removed if
28+
there is no splash screen (such as the default splash screen
29+
defined in @style/LaunchTheme). -->
30+
<meta-data
31+
android:name="io.flutter.app.android.SplashScreenUntilFirstFrame"
32+
android:value="true" />
33+
<intent-filter>
34+
<action android:name="android.intent.action.MAIN"/>
35+
<category android:name="android.intent.category.LAUNCHER"/>
36+
</intent-filter>
37+
</activity>
38+
</application>
39+
</manifest>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package com.example.flutterbloc;
2+
3+
import android.os.Bundle;
4+
import io.flutter.app.FlutterActivity;
5+
import io.flutter.plugins.GeneratedPluginRegistrant;
6+
7+
public class MainActivity extends FlutterActivity {
8+
@Override
9+
protected void onCreate(Bundle savedInstanceState) {
10+
super.onCreate(savedInstanceState);
11+
GeneratedPluginRegistrant.registerWith(this);
12+
}
13+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<!-- Modify this file to customize your launch splash screen -->
3+
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
4+
<item android:drawable="@android:color/white" />
5+
6+
<!-- You can insert your own image assets here -->
7+
<!-- <item>
8+
<bitmap
9+
android:gravity="center"
10+
android:src="@mipmap/launch_image" />
11+
</item> -->
12+
</layer-list>
Loading
Loading
Loading
Loading
Loading
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<resources>
3+
<style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar">
4+
<!-- Show a splash screen on the activity. Automatically removed when
5+
Flutter draws its first frame -->
6+
<item name="android:windowBackground">@drawable/launch_background</item>
7+
</style>
8+
</resources>

0 commit comments

Comments
 (0)