├── android
├── app
│ ├── .gitignore
│ ├── src
│ │ ├── main
│ │ │ ├── res
│ │ │ │ ├── values
│ │ │ │ │ ├── strings.xml
│ │ │ │ │ ├── colors.xml
│ │ │ │ │ └── styles.xml
│ │ │ │ ├── font
│ │ │ │ │ ├── raleway_black.ttf
│ │ │ │ │ └── raleway_regular.ttf
│ │ │ │ ├── mipmap-hdpi
│ │ │ │ │ ├── ic_launcher.png
│ │ │ │ │ └── ic_launcher_round.png
│ │ │ │ ├── mipmap-mdpi
│ │ │ │ │ ├── ic_launcher.png
│ │ │ │ │ └── ic_launcher_round.png
│ │ │ │ ├── mipmap-xhdpi
│ │ │ │ │ ├── ic_launcher.png
│ │ │ │ │ └── ic_launcher_round.png
│ │ │ │ ├── mipmap-xxhdpi
│ │ │ │ │ ├── ic_launcher.png
│ │ │ │ │ └── ic_launcher_round.png
│ │ │ │ ├── mipmap-xxxhdpi
│ │ │ │ │ ├── ic_launcher.png
│ │ │ │ │ └── ic_launcher_round.png
│ │ │ │ ├── drawable
│ │ │ │ │ ├── roundrect_bottom.xml
│ │ │ │ │ ├── ic_search_black.xml
│ │ │ │ │ └── ic_launcher_background.xml
│ │ │ │ ├── mipmap-anydpi-v26
│ │ │ │ │ ├── ic_launcher.xml
│ │ │ │ │ └── ic_launcher_round.xml
│ │ │ │ ├── layout
│ │ │ │ │ ├── activity_main.xml
│ │ │ │ │ ├── cell_movie.xml
│ │ │ │ │ └── fragment_search.xml
│ │ │ │ └── drawable-v24
│ │ │ │ │ └── ic_launcher_foreground.xml
│ │ │ ├── java
│ │ │ │ └── com
│ │ │ │ │ └── github
│ │ │ │ │ └── florent37
│ │ │ │ │ └── mvvmsample
│ │ │ │ │ ├── search
│ │ │ │ │ ├── SearchViewState.kt
│ │ │ │ │ ├── SearchViewModel.kt
│ │ │ │ │ ├── MoviesAdapter.kt
│ │ │ │ │ └── SearchFragment.kt
│ │ │ │ │ ├── omdb
│ │ │ │ │ ├── SearchResponse.kt
│ │ │ │ │ ├── OmdbRepository.kt
│ │ │ │ │ ├── OMDBApi.kt
│ │ │ │ │ └── Movie.kt
│ │ │ │ │ ├── MainActivity.kt
│ │ │ │ │ └── MainApplication.kt
│ │ │ └── AndroidManifest.xml
│ │ ├── test
│ │ │ └── java
│ │ │ │ └── com
│ │ │ │ └── github
│ │ │ │ └── florent37
│ │ │ │ └── mvvmsample
│ │ │ │ └── ExampleUnitTest.kt
│ │ └── androidTest
│ │ │ └── java
│ │ │ └── com
│ │ │ └── github
│ │ │ └── florent37
│ │ │ └── mvvmsample
│ │ │ └── ExampleInstrumentedTest.kt
│ ├── build.gradle
│ └── proguard-rules.pro
├── settings.gradle
├── gradle
│ └── wrapper
│ │ ├── gradle-wrapper.jar
│ │ └── gradle-wrapper.properties
├── .idea
│ ├── modules.xml
│ ├── runConfigurations.xml
│ ├── codeStyles
│ │ └── Project.xml
│ └── misc.xml
├── build.gradle
├── gradle.properties
├── .gitignore
├── gradlew.bat
└── gradlew
├── flutter
├── android
│ ├── gradle.properties
│ ├── .settings
│ │ └── org.eclipse.buildship.core.prefs
│ ├── app
│ │ ├── .settings
│ │ │ └── org.eclipse.buildship.core.prefs
│ │ ├── src
│ │ │ └── main
│ │ │ │ ├── res
│ │ │ │ ├── mipmap-hdpi
│ │ │ │ │ └── ic_launcher.png
│ │ │ │ ├── mipmap-mdpi
│ │ │ │ │ └── ic_launcher.png
│ │ │ │ ├── mipmap-xhdpi
│ │ │ │ │ └── ic_launcher.png
│ │ │ │ ├── mipmap-xxhdpi
│ │ │ │ │ └── ic_launcher.png
│ │ │ │ ├── mipmap-xxxhdpi
│ │ │ │ │ └── ic_launcher.png
│ │ │ │ ├── values
│ │ │ │ │ └── styles.xml
│ │ │ │ └── drawable
│ │ │ │ │ └── launch_background.xml
│ │ │ │ ├── java
│ │ │ │ └── com
│ │ │ │ │ └── example
│ │ │ │ │ └── mvvmsample
│ │ │ │ │ └── MainActivity.java
│ │ │ │ └── AndroidManifest.xml
│ │ ├── proguard-rules.pro
│ │ ├── .classpath
│ │ ├── .project
│ │ └── build.gradle
│ ├── gradle
│ │ └── wrapper
│ │ │ └── gradle-wrapper.properties
│ ├── .project
│ ├── settings.gradle
│ └── build.gradle
├── ios
│ ├── Flutter
│ │ ├── Debug.xcconfig
│ │ ├── Release.xcconfig
│ │ └── AppFrameworkInfo.plist
│ ├── Runner
│ │ ├── AppDelegate.h
│ │ ├── Assets.xcassets
│ │ │ ├── LaunchImage.imageset
│ │ │ │ ├── LaunchImage.png
│ │ │ │ ├── LaunchImage@2x.png
│ │ │ │ ├── LaunchImage@3x.png
│ │ │ │ ├── README.md
│ │ │ │ └── Contents.json
│ │ │ └── AppIcon.appiconset
│ │ │ │ ├── Icon-App-20x20@1x.png
│ │ │ │ ├── Icon-App-20x20@2x.png
│ │ │ │ ├── Icon-App-20x20@3x.png
│ │ │ │ ├── Icon-App-29x29@1x.png
│ │ │ │ ├── Icon-App-29x29@2x.png
│ │ │ │ ├── Icon-App-29x29@3x.png
│ │ │ │ ├── Icon-App-40x40@1x.png
│ │ │ │ ├── Icon-App-40x40@2x.png
│ │ │ │ ├── Icon-App-40x40@3x.png
│ │ │ │ ├── Icon-App-60x60@2x.png
│ │ │ │ ├── Icon-App-60x60@3x.png
│ │ │ │ ├── Icon-App-76x76@1x.png
│ │ │ │ ├── Icon-App-76x76@2x.png
│ │ │ │ ├── Icon-App-1024x1024@1x.png
│ │ │ │ ├── Icon-App-83.5x83.5@2x.png
│ │ │ │ └── Contents.json
│ │ ├── main.m
│ │ ├── AppDelegate.m
│ │ ├── Info.plist
│ │ └── Base.lproj
│ │ │ ├── Main.storyboard
│ │ │ └── LaunchScreen.storyboard
│ ├── Runner.xcworkspace
│ │ └── contents.xcworkspacedata
│ └── Runner.xcodeproj
│ │ ├── project.xcworkspace
│ │ └── contents.xcworkspacedata
│ │ ├── xcshareddata
│ │ └── xcschemes
│ │ │ └── Runner.xcscheme
│ │ └── project.pbxproj
├── generate_json.sh
├── fonts
│ ├── Raleway-Black.ttf
│ └── Raleway-Regular.ttf
├── lib
│ ├── search
│ │ ├── SearchViewState.dart
│ │ ├── SearchViewModel.dart
│ │ └── SearchPage.dart
│ ├── main.dart
│ └── omdb
│ │ ├── OmdbRepository.dart
│ │ └── models
│ │ ├── SearchResponse.dart
│ │ ├── SearchResponse.g.dart
│ │ ├── Movie.dart
│ │ └── Movie.g.dart
├── .metadata
├── README.md
├── test
│ └── widget_test.dart
├── .gitignore
└── pubspec.yaml
└── README.md
/android/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/android/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
2 |
--------------------------------------------------------------------------------
/flutter/android/gradle.properties:
--------------------------------------------------------------------------------
1 | org.gradle.jvmargs=-Xmx1536M
2 |
--------------------------------------------------------------------------------
/flutter/ios/Flutter/Debug.xcconfig:
--------------------------------------------------------------------------------
1 | #include "Generated.xcconfig"
2 |
--------------------------------------------------------------------------------
/flutter/generate_json.sh:
--------------------------------------------------------------------------------
1 | flutter packages pub run build_runner build
2 |
--------------------------------------------------------------------------------
/flutter/ios/Flutter/Release.xcconfig:
--------------------------------------------------------------------------------
1 | #include "Generated.xcconfig"
2 |
--------------------------------------------------------------------------------
/flutter/android/.settings/org.eclipse.buildship.core.prefs:
--------------------------------------------------------------------------------
1 | connection.project.dir=
2 | eclipse.preferences.version=1
3 |
--------------------------------------------------------------------------------
/flutter/android/app/.settings/org.eclipse.buildship.core.prefs:
--------------------------------------------------------------------------------
1 | connection.project.dir=..
2 | eclipse.preferences.version=1
3 |
--------------------------------------------------------------------------------
/flutter/fonts/Raleway-Black.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/florent37/movie_android_flutter/HEAD/flutter/fonts/Raleway-Black.ttf
--------------------------------------------------------------------------------
/flutter/fonts/Raleway-Regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/florent37/movie_android_flutter/HEAD/flutter/fonts/Raleway-Regular.ttf
--------------------------------------------------------------------------------
/android/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | MVVMSample_android
3 |
4 |
--------------------------------------------------------------------------------
/android/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/florent37/movie_android_flutter/HEAD/android/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/android/app/src/main/res/font/raleway_black.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/florent37/movie_android_flutter/HEAD/android/app/src/main/res/font/raleway_black.ttf
--------------------------------------------------------------------------------
/flutter/ios/Runner/AppDelegate.h:
--------------------------------------------------------------------------------
1 | #import
2 | #import
3 |
4 | @interface AppDelegate : FlutterAppDelegate
5 |
6 | @end
7 |
--------------------------------------------------------------------------------
/android/app/src/main/res/font/raleway_regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/florent37/movie_android_flutter/HEAD/android/app/src/main/res/font/raleway_regular.ttf
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/florent37/movie_android_flutter/HEAD/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/florent37/movie_android_flutter/HEAD/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/florent37/movie_android_flutter/HEAD/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/florent37/movie_android_flutter/HEAD/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/florent37/movie_android_flutter/HEAD/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/florent37/movie_android_flutter/HEAD/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/florent37/movie_android_flutter/HEAD/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/florent37/movie_android_flutter/HEAD/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/florent37/movie_android_flutter/HEAD/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/flutter/android/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/florent37/movie_android_flutter/HEAD/flutter/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/flutter/android/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/florent37/movie_android_flutter/HEAD/flutter/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/florent37/movie_android_flutter/HEAD/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/flutter/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/florent37/movie_android_flutter/HEAD/flutter/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/flutter/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/florent37/movie_android_flutter/HEAD/flutter/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/flutter/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/florent37/movie_android_flutter/HEAD/flutter/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/flutter/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/florent37/movie_android_flutter/HEAD/flutter/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png
--------------------------------------------------------------------------------
/flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/florent37/movie_android_flutter/HEAD/flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png
--------------------------------------------------------------------------------
/flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/florent37/movie_android_flutter/HEAD/flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png
--------------------------------------------------------------------------------
/flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/florent37/movie_android_flutter/HEAD/flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png
--------------------------------------------------------------------------------
/flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/florent37/movie_android_flutter/HEAD/flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png
--------------------------------------------------------------------------------
/flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/florent37/movie_android_flutter/HEAD/flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png
--------------------------------------------------------------------------------
/flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/florent37/movie_android_flutter/HEAD/flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png
--------------------------------------------------------------------------------
/flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/florent37/movie_android_flutter/HEAD/flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png
--------------------------------------------------------------------------------
/flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/florent37/movie_android_flutter/HEAD/flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png
--------------------------------------------------------------------------------
/flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/florent37/movie_android_flutter/HEAD/flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png
--------------------------------------------------------------------------------
/flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/florent37/movie_android_flutter/HEAD/flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png
--------------------------------------------------------------------------------
/flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/florent37/movie_android_flutter/HEAD/flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png
--------------------------------------------------------------------------------
/flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/florent37/movie_android_flutter/HEAD/flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png
--------------------------------------------------------------------------------
/flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/florent37/movie_android_flutter/HEAD/flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png
--------------------------------------------------------------------------------
/flutter/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/florent37/movie_android_flutter/HEAD/flutter/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png
--------------------------------------------------------------------------------
/flutter/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/florent37/movie_android_flutter/HEAD/flutter/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png
--------------------------------------------------------------------------------
/flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/florent37/movie_android_flutter/HEAD/flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png
--------------------------------------------------------------------------------
/flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/florent37/movie_android_flutter/HEAD/flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png
--------------------------------------------------------------------------------
/flutter/lib/search/SearchViewState.dart:
--------------------------------------------------------------------------------
1 |
2 | import 'package:mvvm_sample/omdb/models/Movie.dart';
3 |
4 | class SearchViewState {
5 | final List movies;
6 | SearchViewState({this.movies}) : assert(movies != null);
7 | }
--------------------------------------------------------------------------------
/flutter/ios/Runner.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/flutter/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/android/app/src/main/java/com/github/florent37/mvvmsample/search/SearchViewState.kt:
--------------------------------------------------------------------------------
1 | package com.github.florent37.mvvmsample.search
2 |
3 | import com.github.florent37.mvvmsample.omdb.Movie
4 |
5 | class SearchViewState(val movies: List) {
6 |
7 | }
--------------------------------------------------------------------------------
/android/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionBase=GRADLE_USER_HOME
2 | distributionPath=wrapper/dists
3 | distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-all.zip
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 |
--------------------------------------------------------------------------------
/android/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #008577
4 | #00574B
5 | #D81B60
6 |
7 |
--------------------------------------------------------------------------------
/flutter/ios/Runner/main.m:
--------------------------------------------------------------------------------
1 | #import
2 | #import
3 | #import "AppDelegate.h"
4 |
5 | int main(int argc, char* argv[]) {
6 | @autoreleasepool {
7 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/android/app/src/main/java/com/github/florent37/mvvmsample/omdb/SearchResponse.kt:
--------------------------------------------------------------------------------
1 | package com.github.florent37.mvvmsample.omdb
2 |
3 | import com.google.gson.annotations.SerializedName
4 |
5 | class SearchResponse {
6 | @SerializedName("Search")
7 | var movies: List = listOf()
8 | }
9 |
--------------------------------------------------------------------------------
/android/app/src/main/res/drawable/roundrect_bottom.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/flutter/android/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 |
2 | #Flutter Wrapper
3 | -keep class io.flutter.app.** { *; }
4 | -keep class io.flutter.plugin.** { *; }
5 | -keep class io.flutter.util.** { *; }
6 | -keep class io.flutter.view.** { *; }
7 | -keep class io.flutter.** { *; }
8 | -keep class io.flutter.plugins.** { *; }
--------------------------------------------------------------------------------
/flutter/android/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Fri Jun 23 08:50:38 CEST 2017
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.2-all.zip
7 |
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/android/app/src/main/java/com/github/florent37/mvvmsample/omdb/OmdbRepository.kt:
--------------------------------------------------------------------------------
1 | package com.github.florent37.mvvmsample.omdb
2 |
3 | class OmdbRepository(val omdbApi: OMDBApi) {
4 | suspend fun searchMovies(byName: String): List {
5 | val response = omdbApi.searchMovies(byName, OMDBApi.apiKey).await()
6 | return response.movies
7 | }
8 | }
--------------------------------------------------------------------------------
/flutter/.metadata:
--------------------------------------------------------------------------------
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
11 |
--------------------------------------------------------------------------------
/android/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
--------------------------------------------------------------------------------
/flutter/android/app/.classpath:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/android/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/flutter/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md:
--------------------------------------------------------------------------------
1 | # Launch Screen Assets
2 |
3 | You can customize the launch screen with your own desired assets by replacing the image files in this directory.
4 |
5 | You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images.
--------------------------------------------------------------------------------
/flutter/android/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 |
9 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # movie_android_flutter
2 |
3 | A sample movie app, developed on flutter, then on android
4 |
5 | This repository was used to write an article on medium : https://proandroiddev.com/mythbuster-10-rumors-about-flutter-why-its-not-worse-than-android-kotlin-f1a1acbe587d
6 |
7 | Flutter : https://github.com/florent37/movie_android_flutter/tree/master/flutter
8 |
9 | Android : https://github.com/florent37/movie_android_flutter/tree/master/android
10 |
--------------------------------------------------------------------------------
/android/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/flutter/android/app/src/main/java/com/example/mvvmsample/MainActivity.java:
--------------------------------------------------------------------------------
1 | package com.example.mvvmsample;
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 | }
14 |
--------------------------------------------------------------------------------
/android/app/src/test/java/com/github/florent37/mvvmsample/ExampleUnitTest.kt:
--------------------------------------------------------------------------------
1 | package com.github.florent37.mvvmsample
2 |
3 | import org.junit.Test
4 |
5 | import org.junit.Assert.*
6 |
7 | /**
8 | * Example local unit test, which will execute on the development machine (host).
9 | *
10 | * See [testing documentation](http://d.android.com/tools/testing).
11 | */
12 | class ExampleUnitTest {
13 | @Test
14 | fun addition_isCorrect() {
15 | assertEquals(4, 2 + 2)
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/flutter/ios/Runner/AppDelegate.m:
--------------------------------------------------------------------------------
1 | #include "AppDelegate.h"
2 | #include "GeneratedPluginRegistrant.h"
3 |
4 | @implementation AppDelegate
5 |
6 | - (BOOL)application:(UIApplication *)application
7 | didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
8 | [GeneratedPluginRegistrant registerWithRegistry:self];
9 | // Override point for customization after application launch.
10 | return [super application:application didFinishLaunchingWithOptions:launchOptions];
11 | }
12 |
13 | @end
14 |
--------------------------------------------------------------------------------
/android/app/src/main/java/com/github/florent37/mvvmsample/omdb/OMDBApi.kt:
--------------------------------------------------------------------------------
1 | package com.github.florent37.mvvmsample.omdb
2 |
3 | import kotlinx.coroutines.Deferred
4 | import retrofit2.http.GET
5 | import retrofit2.http.Query
6 |
7 | interface OMDBApi {
8 | @GET("/")
9 | fun searchMovies(@Query("s") name: String, @Query("apiKey") apikey: String) : Deferred
10 |
11 | companion object {
12 | val apiKey = "86850a46"
13 | val baseUrl = "https://www.omdbapi.com/"
14 | }
15 | }
--------------------------------------------------------------------------------
/flutter/android/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | android
4 | Project android created by Buildship.
5 |
6 |
7 |
8 |
9 | org.eclipse.buildship.core.gradleprojectbuilder
10 |
11 |
12 |
13 |
14 |
15 | org.eclipse.buildship.core.gradleprojectnature
16 |
17 |
18 |
--------------------------------------------------------------------------------
/android/app/src/main/java/com/github/florent37/mvvmsample/omdb/Movie.kt:
--------------------------------------------------------------------------------
1 | package com.github.florent37.mvvmsample.omdb
2 |
3 | import com.google.gson.annotations.SerializedName
4 |
5 | class Movie {
6 | @SerializedName("Title")
7 | var title : String = ""
8 | @SerializedName("Year")
9 | var year : String = ""
10 | @SerializedName("ImdbID")
11 | var imdbID : String = ""
12 | @SerializedName("Type")
13 | var type : String = ""
14 | @SerializedName("Poster")
15 | var poster : String = ""
16 | }
--------------------------------------------------------------------------------
/flutter/android/app/src/main/res/drawable/launch_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
12 |
13 |
--------------------------------------------------------------------------------
/flutter/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "LaunchImage.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "filename" : "LaunchImage@2x.png",
11 | "scale" : "2x"
12 | },
13 | {
14 | "idiom" : "universal",
15 | "filename" : "LaunchImage@3x.png",
16 | "scale" : "3x"
17 | }
18 | ],
19 | "info" : {
20 | "version" : 1,
21 | "author" : "xcode"
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/flutter/android/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
2 |
3 | def flutterProjectRoot = rootProject.projectDir.parentFile.toPath()
4 |
5 | def plugins = new Properties()
6 | def pluginsFile = new File(flutterProjectRoot.toFile(), '.flutter-plugins')
7 | if (pluginsFile.exists()) {
8 | pluginsFile.withReader('UTF-8') { reader -> plugins.load(reader) }
9 | }
10 |
11 | plugins.each { name, path ->
12 | def pluginDirectory = flutterProjectRoot.resolve(path).resolve('android').toFile()
13 | include ":$name"
14 | project(":$name").projectDir = pluginDirectory
15 | }
16 |
--------------------------------------------------------------------------------
/flutter/lib/main.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:mvvm_sample/search/SearchPage.dart';
3 |
4 | void main() => runApp(MyApp());
5 |
6 | class MyApp extends StatelessWidget {
7 | @override
8 | Widget build(BuildContext context) {
9 | return MaterialApp(
10 | debugShowCheckedModeBanner: false,
11 | title: 'Flutter Demo',
12 | theme: ThemeData(
13 | primarySwatch: Colors.blue,
14 |
15 | ),
16 | home: Scaffold(
17 | body: SafeArea(child: SearchPage())));
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/flutter/lib/omdb/OmdbRepository.dart:
--------------------------------------------------------------------------------
1 | import 'dart:convert';
2 |
3 | import 'package:http/http.dart' as http;
4 | import 'package:mvvm_sample/omdb/models/Movie.dart';
5 | import 'package:mvvm_sample/omdb/models/SearchResponse.dart';
6 |
7 | class OmdbRepository {
8 | final apiKey = "86850a46";
9 | const OmdbRepository();
10 |
11 | Future> searchMovies(String byName) async {
12 | final response = await http.get('http://www.omdbapi.com/?s=$byName&apikey=$apiKey');
13 | final jsonValue = json.decode(response.body);
14 | return SearchResponse.fromJson(jsonValue).movies;
15 | }
16 | }
--------------------------------------------------------------------------------
/android/app/src/main/res/drawable/ic_search_black.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/flutter/android/build.gradle:
--------------------------------------------------------------------------------
1 | buildscript {
2 | repositories {
3 | google()
4 | jcenter()
5 | }
6 |
7 | dependencies {
8 | classpath 'com.android.tools.build:gradle:3.2.1'
9 | }
10 | }
11 |
12 | allprojects {
13 | repositories {
14 | google()
15 | jcenter()
16 | }
17 | }
18 |
19 | rootProject.buildDir = '../build'
20 | subprojects {
21 | project.buildDir = "${rootProject.buildDir}/${project.name}"
22 | }
23 | subprojects {
24 | project.evaluationDependsOn(':app')
25 | }
26 |
27 | task clean(type: Delete) {
28 | delete rootProject.buildDir
29 | }
30 |
--------------------------------------------------------------------------------
/android/.idea/runConfigurations.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
11 |
12 |
--------------------------------------------------------------------------------
/android/app/src/main/java/com/github/florent37/mvvmsample/MainActivity.kt:
--------------------------------------------------------------------------------
1 | package com.github.florent37.mvvmsample
2 |
3 | import android.os.Bundle
4 | import androidx.appcompat.app.AppCompatActivity
5 | import com.github.florent37.mvvmsample.search.SearchFragment
6 |
7 | class MainActivity : AppCompatActivity() {
8 |
9 | override fun onCreate(savedInstanceState: Bundle?) {
10 | super.onCreate(savedInstanceState)
11 | setContentView(R.layout.activity_main)
12 |
13 | supportFragmentManager.beginTransaction()
14 | .replace(R.id.container, SearchFragment())
15 | .commitAllowingStateLoss()
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/flutter/README.md:
--------------------------------------------------------------------------------
1 | # mvvm_sample
2 |
3 | A new Flutter project.
4 |
5 | ## Getting Started
6 |
7 | This project is a starting point for a Flutter application.
8 |
9 | A few resources to get you started if this is your first Flutter project:
10 |
11 | - [Lab: Write your first Flutter app](https://flutter.io/docs/get-started/codelab)
12 | - [Cookbook: Useful Flutter samples](https://flutter.io/docs/cookbook)
13 |
14 | For help getting started with Flutter, view our
15 | [online documentation](https://flutter.io/docs), which offers tutorials,
16 | samples, guidance on mobile development, and a full API reference.
17 |
18 | to generate json bindings run : sh generate_json.sh
19 |
--------------------------------------------------------------------------------
/flutter/android/app/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | app
4 | Project app created by Buildship.
5 |
6 |
7 |
8 |
9 | org.eclipse.jdt.core.javabuilder
10 |
11 |
12 |
13 |
14 | org.eclipse.buildship.core.gradleprojectbuilder
15 |
16 |
17 |
18 |
19 |
20 | org.eclipse.jdt.core.javanature
21 | org.eclipse.buildship.core.gradleprojectnature
22 |
23 |
24 |
--------------------------------------------------------------------------------
/flutter/lib/omdb/models/SearchResponse.dart:
--------------------------------------------------------------------------------
1 | import 'package:json_annotation/json_annotation.dart';
2 | import 'package:mvvm_sample/omdb/models/Movie.dart';
3 |
4 | /// This allows the `SearchResponse` class to access private members in
5 | /// the generated file. The value for this is *.g.dart, where
6 | /// the star denotes the source file name.
7 | part 'SearchResponse.g.dart';
8 |
9 | @JsonSerializable()
10 | class SearchResponse {
11 | @JsonKey(name: "Search")
12 | List movies;
13 |
14 | SearchResponse({this.movies});
15 |
16 | factory SearchResponse.fromJson(Map json) => _$SearchResponseFromJson(json);
17 | Map toJson() => _$SearchResponseToJson(this);
18 | }
--------------------------------------------------------------------------------
/flutter/lib/omdb/models/SearchResponse.g.dart:
--------------------------------------------------------------------------------
1 | // GENERATED CODE - DO NOT MODIFY BY HAND
2 |
3 | part of 'SearchResponse.dart';
4 |
5 | // **************************************************************************
6 | // JsonSerializableGenerator
7 | // **************************************************************************
8 |
9 | SearchResponse _$SearchResponseFromJson(Map json) {
10 | return SearchResponse(
11 | movies: (json['Search'] as List)
12 | ?.map((e) =>
13 | e == null ? null : Movie.fromJson(e as Map))
14 | ?.toList());
15 | }
16 |
17 | Map _$SearchResponseToJson(SearchResponse instance) =>
18 | {'Search': instance.movies};
19 |
--------------------------------------------------------------------------------
/android/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 |
3 | buildscript {
4 | ext.kotlin_version = '1.3.10'
5 | repositories {
6 | google()
7 | jcenter()
8 | }
9 | dependencies {
10 | classpath 'com.android.tools.build:gradle:3.2.1'
11 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
12 |
13 | // NOTE: Do not place your application dependencies here; they belong
14 | // in the individual module build.gradle files
15 | }
16 | }
17 |
18 | allprojects {
19 | repositories {
20 | google()
21 | jcenter()
22 | }
23 | }
24 |
25 | task clean(type: Delete) {
26 | delete rootProject.buildDir
27 | }
28 |
--------------------------------------------------------------------------------
/flutter/lib/search/SearchViewModel.dart:
--------------------------------------------------------------------------------
1 | import 'package:mvvm_sample/omdb/OmdbRepository.dart';
2 | import 'package:mvvm_sample/search/SearchViewState.dart';
3 | import 'dart:async';
4 |
5 | class SearchViewModel {
6 | //Stream <=> MediatorLiveData
7 | final StreamController _viewModelController = StreamController();
8 | final OmdbRepository _repository;
9 |
10 | //Stream <=> LiveData
11 | Stream get viewState => _viewModelController.stream;
12 |
13 | //constructor
14 | SearchViewModel(this._repository) {
15 | _start();
16 | }
17 |
18 | void _start(){
19 | this.search("avengers");
20 | }
21 |
22 | void search(String name) async {
23 | var movies = await _repository.searchMovies(name);
24 | _viewModelController.add(SearchViewState(movies: movies));
25 | }
26 |
27 | }
--------------------------------------------------------------------------------
/android/app/src/androidTest/java/com/github/florent37/mvvmsample/ExampleInstrumentedTest.kt:
--------------------------------------------------------------------------------
1 | package com.github.florent37.mvvmsample
2 |
3 | import android.support.test.InstrumentationRegistry
4 | import android.support.test.runner.AndroidJUnit4
5 |
6 | import org.junit.Test
7 | import org.junit.runner.RunWith
8 |
9 | import org.junit.Assert.*
10 |
11 | /**
12 | * Instrumented test, which will execute on an Android device.
13 | *
14 | * See [testing documentation](http://d.android.com/tools/testing).
15 | */
16 | @RunWith(AndroidJUnit4::class)
17 | class ExampleInstrumentedTest {
18 | @Test
19 | fun useAppContext() {
20 | // Context of the app under test.
21 | val appContext = InstrumentationRegistry.getTargetContext()
22 | assertEquals("com.github.florent37.mvvmsample", appContext.packageName)
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/flutter/lib/omdb/models/Movie.dart:
--------------------------------------------------------------------------------
1 | import 'package:json_annotation/json_annotation.dart';
2 |
3 | /// This allows the `Movie` class to access private members in
4 | /// the generated file. The value for this is *.g.dart, where
5 | /// the star denotes the source file name.
6 | part 'Movie.g.dart';
7 |
8 | @JsonSerializable()
9 | class Movie {
10 | @JsonKey(name: "Title")
11 | final String title;
12 | @JsonKey(name: "Year")
13 | final String year;
14 | @JsonKey(name: "ImdbID")
15 | final String imdbID;
16 | @JsonKey(name: "Type")
17 | final String type;
18 | @JsonKey(name: "Poster")
19 | final String poster;
20 |
21 | Movie({this.title, this.year, this.imdbID, this.type, this.poster});
22 |
23 | factory Movie.fromJson(Map json) => _$MovieFromJson(json);
24 | Map toJson() => _$MovieToJson(this);
25 |
26 | }
--------------------------------------------------------------------------------
/flutter/lib/omdb/models/Movie.g.dart:
--------------------------------------------------------------------------------
1 | // GENERATED CODE - DO NOT MODIFY BY HAND
2 |
3 | part of 'Movie.dart';
4 |
5 | // **************************************************************************
6 | // JsonSerializableGenerator
7 | // **************************************************************************
8 |
9 | Movie _$MovieFromJson(Map json) {
10 | return Movie(
11 | title: json['Title'] as String,
12 | year: json['Year'] as String,
13 | imdbID: json['ImdbID'] as String,
14 | type: json['Type'] as String,
15 | poster: json['Poster'] as String);
16 | }
17 |
18 | Map _$MovieToJson(Movie instance) => {
19 | 'Title': instance.title,
20 | 'Year': instance.year,
21 | 'ImdbID': instance.imdbID,
22 | 'Type': instance.type,
23 | 'Poster': instance.poster
24 | };
25 |
--------------------------------------------------------------------------------
/flutter/ios/Flutter/AppFrameworkInfo.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | App
9 | CFBundleIdentifier
10 | io.flutter.flutter.app
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | App
15 | CFBundlePackageType
16 | FMWK
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1.0
23 | MinimumOSVersion
24 | 8.0
25 |
26 |
27 |
--------------------------------------------------------------------------------
/android/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 | # IDE (e.g. Android Studio) users:
3 | # Gradle settings configured through the IDE *will override*
4 | # any settings specified in this file.
5 | # For more details on how to configure your build environment visit
6 | # http://www.gradle.org/docs/current/userguide/build_environment.html
7 | # Specifies the JVM arguments used for the daemon process.
8 | # The setting is particularly useful for tweaking memory settings.
9 | org.gradle.jvmargs=-Xmx1536m
10 | # When configured, Gradle will run in incubating parallel mode.
11 | # This option should only be used with decoupled projects. More details, visit
12 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
13 | # org.gradle.parallel=true
14 | # Kotlin code style for this project: "official" or "obsolete":
15 | kotlin.code.style=official
16 | android.useAndroidX=true
17 | android.enableJetifier=true
18 |
--------------------------------------------------------------------------------
/android/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/flutter/test/widget_test.dart:
--------------------------------------------------------------------------------
1 | // This is a basic Flutter widget test.
2 | //
3 | // To perform an interaction with a widget in your test, use the WidgetTester
4 | // utility that Flutter provides. For example, you can send tap and scroll
5 | // gestures. You can also use WidgetTester to find child widgets in the widget
6 | // tree, read text, and verify that the values of widget properties are correct.
7 |
8 | import 'package:flutter/material.dart';
9 | import 'package:flutter_test/flutter_test.dart';
10 |
11 | import 'package:mvvm_sample/main.dart';
12 |
13 | void main() {
14 | testWidgets('Counter increments smoke test', (WidgetTester tester) async {
15 | // Build our app and trigger a frame.
16 | await tester.pumpWidget(MyApp());
17 |
18 | // Verify that our counter starts at 0.
19 | expect(find.text('0'), findsOneWidget);
20 | expect(find.text('1'), findsNothing);
21 |
22 | // Tap the '+' icon and trigger a frame.
23 | await tester.tap(find.byIcon(Icons.add));
24 | await tester.pump();
25 |
26 | // Verify that our counter has incremented.
27 | expect(find.text('0'), findsNothing);
28 | expect(find.text('1'), findsOneWidget);
29 | });
30 | }
31 |
--------------------------------------------------------------------------------
/android/app/src/main/java/com/github/florent37/mvvmsample/search/SearchViewModel.kt:
--------------------------------------------------------------------------------
1 | package com.github.florent37.mvvmsample.search
2 |
3 | import android.app.Application
4 | import androidx.lifecycle.AndroidViewModel
5 | import androidx.lifecycle.LiveData
6 | import androidx.lifecycle.MutableLiveData
7 | import com.github.florent37.mvvmsample.mainApplication
8 | import kotlinx.coroutines.*
9 | import kotlin.coroutines.CoroutineContext
10 |
11 | class SearchViewModel(application: Application) : AndroidViewModel(application), CoroutineScope {
12 | private val job = Job()
13 | override val coroutineContext: CoroutineContext
14 | get() = job + Dispatchers.Main
15 |
16 | private val mutableViewState = MutableLiveData()
17 | val viewState : LiveData = mutableViewState
18 |
19 | private val repository by lazy {
20 | mainApplication.omdbRepository
21 | }
22 |
23 | init {
24 | start()
25 | }
26 |
27 | private fun start(){
28 | search("avengers")
29 | }
30 |
31 | fun search(name : String) {
32 | launch {
33 | val movies = repository.searchMovies(name)
34 | mutableViewState.postValue(SearchViewState(movies))
35 | }
36 |
37 | }
38 | }
--------------------------------------------------------------------------------
/android/.gitignore:
--------------------------------------------------------------------------------
1 | # Built application files
2 | *.apk
3 | *.ap_
4 | *.aab
5 |
6 | # Files for the ART/Dalvik VM
7 | *.dex
8 |
9 | # Java class files
10 | *.class
11 |
12 | # Generated files
13 | bin/
14 | gen/
15 | out/
16 |
17 | # Gradle files
18 | .gradle/
19 | build/
20 |
21 | # Local configuration file (sdk path, etc)
22 | local.properties
23 |
24 | # Proguard folder generated by Eclipse
25 | proguard/
26 |
27 | # Log Files
28 | *.log
29 |
30 | # Android Studio Navigation editor temp files
31 | .navigation/
32 |
33 | # Android Studio captures folder
34 | captures/
35 |
36 | # IntelliJ
37 | *.iml
38 | .idea/workspace.xml
39 | .idea/tasks.xml
40 | .idea/gradle.xml
41 | .idea/assetWizardSettings.xml
42 | .idea/dictionaries
43 | .idea/libraries
44 | .idea/caches
45 |
46 | # Keystore files
47 | # Uncomment the following lines if you do not want to check your keystore files in.
48 | #*.jks
49 | #*.keystore
50 |
51 | # External native build folder generated in Android Studio 2.2 and later
52 | .externalNativeBuild
53 |
54 | # Google Services (e.g. APIs or Firebase)
55 | google-services.json
56 |
57 | # Freeline
58 | freeline.py
59 | freeline/
60 | freeline_project_description.json
61 |
62 | # fastlane
63 | fastlane/report.xml
64 | fastlane/Preview.html
65 | fastlane/screenshots
66 | fastlane/test_output
67 | fastlane/readme.md
--------------------------------------------------------------------------------
/android/app/src/main/java/com/github/florent37/mvvmsample/MainApplication.kt:
--------------------------------------------------------------------------------
1 | package com.github.florent37.mvvmsample
2 |
3 | import android.app.Application
4 | import com.github.florent37.mvvmsample.omdb.OMDBApi
5 | import com.github.florent37.mvvmsample.omdb.OmdbRepository
6 | import com.jakewharton.retrofit2.adapter.kotlin.coroutines.CoroutineCallAdapterFactory
7 | import okhttp3.OkHttpClient
8 | import okhttp3.logging.HttpLoggingInterceptor
9 | import retrofit2.Retrofit
10 | import retrofit2.converter.gson.GsonConverterFactory
11 |
12 | lateinit var mainApplication: MainApplication
13 |
14 | class MainApplication : Application() {
15 | val api by lazy {
16 | Retrofit.Builder()
17 | .baseUrl(OMDBApi.baseUrl)
18 | .client(
19 | OkHttpClient.Builder()
20 | .addInterceptor(HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BASIC))
21 | .build()
22 | )
23 | .addConverterFactory(GsonConverterFactory.create())
24 | .addCallAdapterFactory(CoroutineCallAdapterFactory())
25 | .build()
26 | .create(OMDBApi::class.java)
27 | }
28 |
29 | val omdbRepository by lazy {
30 | OmdbRepository(api)
31 | }
32 |
33 | override fun onCreate() {
34 | super.onCreate()
35 | mainApplication = this
36 | }
37 |
38 |
39 | }
--------------------------------------------------------------------------------
/android/app/src/main/res/layout/cell_movie.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
23 |
24 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/flutter/.gitignore:
--------------------------------------------------------------------------------
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
72 |
--------------------------------------------------------------------------------
/flutter/ios/Runner/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | mvvm_sample
15 | CFBundlePackageType
16 | APPL
17 | CFBundleShortVersionString
18 | $(FLUTTER_BUILD_NAME)
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | $(FLUTTER_BUILD_NUMBER)
23 | LSRequiresIPhoneOS
24 |
25 | UILaunchStoryboardName
26 | LaunchScreen
27 | UIMainStoryboardFile
28 | Main
29 | UISupportedInterfaceOrientations
30 |
31 | UIInterfaceOrientationPortrait
32 | UIInterfaceOrientationLandscapeLeft
33 | UIInterfaceOrientationLandscapeRight
34 |
35 | UISupportedInterfaceOrientations~ipad
36 |
37 | UIInterfaceOrientationPortrait
38 | UIInterfaceOrientationPortraitUpsideDown
39 | UIInterfaceOrientationLandscapeLeft
40 | UIInterfaceOrientationLandscapeRight
41 |
42 | UIViewControllerBasedStatusBarAppearance
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/flutter/ios/Runner/Base.lproj/Main.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/android/app/src/main/java/com/github/florent37/mvvmsample/search/MoviesAdapter.kt:
--------------------------------------------------------------------------------
1 | package com.github.florent37.mvvmsample.search
2 |
3 | import android.view.LayoutInflater
4 | import android.view.View
5 | import android.view.ViewGroup
6 | import androidx.recyclerview.widget.RecyclerView
7 | import com.bumptech.glide.Glide
8 | import com.github.florent37.mvvmsample.R
9 | import com.github.florent37.mvvmsample.omdb.Movie
10 | import kotlinx.android.synthetic.main.cell_movie.view.*
11 |
12 | class MoviesAdapter : RecyclerView.Adapter() {
13 |
14 | var clickListener: ((Movie) -> Unit)? = null
15 |
16 | var items = listOf()
17 | set(value) {
18 | field = value
19 | notifyDataSetChanged()
20 | }
21 |
22 | override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MovieViewHolder {
23 | val view = LayoutInflater.from(parent.context).inflate(R.layout.cell_movie, parent, false)
24 | return MovieViewHolder(view) {
25 | clickListener?.invoke(it)
26 | }
27 | }
28 |
29 | override fun getItemCount() = items.size
30 |
31 | override fun onBindViewHolder(holder: MovieViewHolder, position: Int) {
32 | holder.bind(items[position])
33 | }
34 |
35 | }
36 |
37 | class MovieViewHolder(view: View, val clickListener: (Movie) -> Unit) :
38 | RecyclerView.ViewHolder(view) {
39 |
40 | var movie: Movie? = null
41 | var image = view.image
42 |
43 | init {
44 | itemView.setOnClickListener {
45 | movie?.let(clickListener)
46 | }
47 | }
48 |
49 | fun bind(movie: Movie) {
50 | this.movie = movie
51 |
52 | Glide.with(image).load(movie.poster).into(image)
53 | }
54 | }
--------------------------------------------------------------------------------
/android/.idea/codeStyles/Project.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/android/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 | apply plugin: 'kotlin-android'
3 | apply plugin: 'kotlin-android-extensions'
4 | apply plugin: 'kotlin-kapt'
5 |
6 | android {
7 | compileSdkVersion 28
8 | defaultConfig {
9 | applicationId "com.github.florent37.mvvmsample"
10 | minSdkVersion 14
11 | targetSdkVersion 28
12 | versionCode 1
13 | versionName "1.0"
14 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
15 | }
16 | buildTypes {
17 | release {
18 | minifyEnabled true
19 | shrinkResources true
20 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
21 | }
22 | }
23 | }
24 |
25 | dependencies {
26 | implementation fileTree(dir: 'libs', include: ['*.jar'])
27 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
28 | implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.0.1'
29 | implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.0.1'
30 | implementation 'com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:0.9.2'
31 | implementation 'androidx.appcompat:appcompat:1.1.0-alpha01'
32 | implementation 'androidx.constraintlayout:constraintlayout:2.0.0-alpha2'
33 | implementation 'com.squareup.retrofit2:retrofit:2.5.0'
34 | implementation 'com.squareup.retrofit2:converter-gson:2.5.0'
35 |
36 | def lifecycle_version = "2.0.0"
37 | implementation "androidx.lifecycle:lifecycle-extensions:$lifecycle_version"
38 |
39 | implementation 'com.github.bumptech.glide:glide:4.8.0'
40 | kapt 'com.github.bumptech.glide:compiler:4.8.0'
41 |
42 | implementation 'jp.wasabeef:glide-transformations:4.0.1'
43 | implementation 'com.github.florent37:shapeofview:1.4.6'
44 |
45 | implementation 'com.squareup.okhttp3:logging-interceptor:3.11.0'
46 |
47 |
48 | }
49 |
--------------------------------------------------------------------------------
/android/app/src/main/res/drawable-v24/ic_launcher_foreground.xml:
--------------------------------------------------------------------------------
1 |
7 |
12 |
13 |
19 |
22 |
25 |
26 |
27 |
28 |
34 |
35 |
--------------------------------------------------------------------------------
/flutter/android/app/build.gradle:
--------------------------------------------------------------------------------
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.mvvmsample"
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 | signingConfig signingConfigs.debug
47 |
48 | minifyEnabled true
49 | useProguard true
50 |
51 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
52 | }
53 | }
54 | }
55 |
56 | flutter {
57 | source '../..'
58 | }
59 |
60 | dependencies {
61 | testImplementation 'junit:junit:4.12'
62 | androidTestImplementation 'com.android.support.test:runner:1.0.2'
63 | androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
64 | }
65 |
--------------------------------------------------------------------------------
/flutter/android/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
8 |
9 |
10 |
15 |
19 |
26 |
30 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
--------------------------------------------------------------------------------
/flutter/ios/Runner/Base.lproj/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/android/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | set DIRNAME=%~dp0
12 | if "%DIRNAME%" == "" set DIRNAME=.
13 | set APP_BASE_NAME=%~n0
14 | set APP_HOME=%DIRNAME%
15 |
16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
17 | set DEFAULT_JVM_OPTS=
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windows variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 |
53 | :win9xME_args
54 | @rem Slurp the command line arguments.
55 | set CMD_LINE_ARGS=
56 | set _SKIP=2
57 |
58 | :win9xME_args_slurp
59 | if "x%~1" == "x" goto execute
60 |
61 | set CMD_LINE_ARGS=%*
62 |
63 | :execute
64 | @rem Setup the command line
65 |
66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
67 |
68 | @rem Execute Gradle
69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
70 |
71 | :end
72 | @rem End local scope for the variables with windows NT shell
73 | if "%ERRORLEVEL%"=="0" goto mainEnd
74 |
75 | :fail
76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
77 | rem the _cmd.exe /c_ return code!
78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
79 | exit /b 1
80 |
81 | :mainEnd
82 | if "%OS%"=="Windows_NT" endlocal
83 |
84 | :omega
85 |
--------------------------------------------------------------------------------
/flutter/pubspec.yaml:
--------------------------------------------------------------------------------
1 | name: mvvm_sample
2 | description: A new Flutter project.
3 |
4 | # The following defines the version and build number for your application.
5 | # A version number is three numbers separated by dots, like 1.2.43
6 | # followed by an optional build number separated by a +.
7 | # Both the version and the builder number may be overridden in flutter
8 | # build by specifying --build-name and --build-number, respectively.
9 | # Read more about versioning at semver.org.
10 | version: 1.0.0+1
11 |
12 | environment:
13 | sdk: ">=2.0.0-dev.68.0 <3.0.0"
14 |
15 | dependencies:
16 | flutter:
17 | sdk: flutter
18 |
19 | # The following adds the Cupertino Icons font to your application.
20 | # Use with the CupertinoIcons class for iOS style icons.
21 | http: ^0.12.0
22 | json_annotation: ^2.0.0
23 |
24 | dev_dependencies:
25 | flutter_test:
26 | sdk: flutter
27 | build_runner: ^1.0.0
28 | json_serializable: ^2.0.0
29 |
30 |
31 |
32 | # For information on the generic Dart part of this file, see the
33 | # following page: https://www.dartlang.org/tools/pub/pubspec
34 |
35 | # The following section is specific to Flutter.
36 | flutter:
37 |
38 | # The following line ensures that the Material Icons font is
39 | # included with your application, so that you can use the icons in
40 | # the material Icons class.
41 | uses-material-design: true
42 |
43 | # To add assets to your application, add an assets section, like this:
44 | # assets:
45 | # - images/a_dot_burr.jpeg
46 | # - images/a_dot_ham.jpeg
47 |
48 | # An image asset can refer to one or more resolution-specific "variants", see
49 | # https://flutter.io/assets-and-images/#resolution-aware.
50 |
51 | # For details regarding adding assets from package dependencies, see
52 | # https://flutter.io/assets-and-images/#from-packages
53 |
54 | # To add custom fonts to your application, add a fonts section here,
55 | # in this "flutter" section. Each entry in this list should have a
56 | # "family" key with the font family name, and a "fonts" key with a
57 | # list giving the asset and other descriptors for the font. For
58 | # example:
59 | fonts:
60 | - family: Raleway
61 | fonts:
62 | - asset: fonts/Raleway-Regular.ttf
63 | - asset: fonts/Raleway-Black.ttf
64 | weight: 700
65 | # - family: Trajan Pro
66 | # fonts:
67 | # - asset: fonts/TrajanPro.ttf
68 | # - asset: fonts/TrajanPro_Bold.ttf
69 | # weight: 700
70 | #
71 | # For details regarding fonts from package dependencies,
72 | # see https://flutter.io/custom-fonts/#from-packages
73 |
--------------------------------------------------------------------------------
/android/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # You can control the set of applied configuration files using the
3 | # proguardFiles setting in build.gradle.
4 | #
5 | # For more details, see
6 | # http://developer.android.com/guide/developing/tools/proguard.html
7 |
8 | # If your project uses WebView with JS, uncomment the following
9 | # and specify the fully qualified class name to the JavaScript interface
10 | # class:
11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12 | # public *;
13 | #}
14 |
15 | # Uncomment this to preserve the line number information for
16 | # debugging stack traces.
17 | #-keepattributes SourceFile,LineNumberTable
18 |
19 | # If you keep the line number information, uncomment this to
20 | # hide the original source file name.
21 | #-renamesourcefileattribute SourceFile
22 |
23 |
24 | -keep public class * implements com.bumptech.glide.module.GlideModule
25 | -keep public class * extends com.bumptech.glide.module.AppGlideModule
26 | -keep public enum com.bumptech.glide.load.ImageHeaderParser$** {
27 | **[] $VALUES;
28 | public *;
29 | }
30 |
31 |
32 | -keep class com.squareup.okhttp3.** {
33 | *;
34 | }
35 | -keepattributes Signature
36 | -keepattributes Annotation
37 | -keep class okhttp3.** { *; }
38 | -keep interface okhttp3.** { *; }
39 | -dontwarn okhttp3.**
40 | -dontwarn okio.**
41 | # JSR 305 annotations are for embedding nullability information.
42 | -dontwarn javax.annotation.**
43 |
44 | # A resource is loaded with a relative path so the package of this class must be preserved.
45 | -keepnames class okhttp3.internal.publicsuffix.PublicSuffixDatabase
46 |
47 | # Animal Sniffer compileOnly dependency to ensure APIs are compatible with older versions of Java.
48 | -dontwarn org.codehaus.mojo.animal_sniffer.*
49 |
50 | # OkHttp platform used only on JVM and when Conscrypt dependency is available.
51 | -dontwarn okhttp3.internal.platform.ConscryptPlatform
52 |
53 | # Retrofit does reflection on generic parameters. InnerClasses is required to use Signature and
54 | # EnclosingMethod is required to use InnerClasses.
55 | -keepattributes Signature, InnerClasses, EnclosingMethod
56 |
57 | # Retain service method parameters when optimizing.
58 | -keepclassmembers,allowshrinking,allowobfuscation interface * {
59 | @retrofit2.http.* ;
60 | }
61 |
62 | # Ignore annotation used for build tooling.
63 | -dontwarn org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement
64 |
65 | # Ignore JSR 305 annotations for embedding nullability information.
66 | -dontwarn javax.annotation.**
67 |
68 | # Guarded by a NoClassDefFoundError try/catch and only used when on the classpath.
69 | -dontwarn kotlin.Unit
70 |
71 | # Top-level functions that can only be used by Kotlin.
72 | -dontwarn retrofit2.-KotlinExtensions
--------------------------------------------------------------------------------
/android/app/src/main/java/com/github/florent37/mvvmsample/search/SearchFragment.kt:
--------------------------------------------------------------------------------
1 | package com.github.florent37.mvvmsample.search
2 |
3 | import android.os.Bundle
4 | import android.view.KeyEvent
5 | import android.view.LayoutInflater
6 | import android.view.View
7 | import android.view.ViewGroup
8 | import androidx.fragment.app.Fragment
9 | import androidx.lifecycle.Observer
10 | import androidx.lifecycle.ViewModelProviders
11 | import androidx.recyclerview.widget.LinearLayoutManager
12 | import androidx.recyclerview.widget.RecyclerView
13 | import com.bumptech.glide.Glide
14 | import com.bumptech.glide.request.RequestOptions.bitmapTransform
15 | import com.github.florent37.mvvmsample.R
16 | import com.github.florent37.mvvmsample.omdb.Movie
17 | import jp.wasabeef.glide.transformations.BlurTransformation
18 | import kotlinx.android.synthetic.main.fragment_search.*
19 |
20 | class SearchFragment : Fragment() {
21 |
22 | private lateinit var viewModel: SearchViewModel
23 | private var clickedMovie: Movie? = null
24 | set(value) {
25 | field = value
26 | if (value != null) {
27 | title.text = value.title.replace(" ", "\n").toUpperCase()
28 | details.text = "${value.type} (${value.year})";
29 | Glide.with(this)
30 | .load(value.poster)
31 | .apply(bitmapTransform(BlurTransformation(10, 2)))
32 | .into(backgroundImage)
33 | }
34 | }
35 |
36 | private lateinit var adapter: MoviesAdapter;
37 |
38 | override fun onCreateView(
39 | inflater: LayoutInflater,
40 | container: ViewGroup?,
41 | savedInstanceState: Bundle?
42 | ) = inflater.inflate(R.layout.fragment_search, container, false)
43 |
44 | override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
45 | super.onViewCreated(view, savedInstanceState)
46 |
47 | adapter = MoviesAdapter()
48 | recyclerView.adapter = adapter
49 | recyclerView.layoutManager = LinearLayoutManager(context, RecyclerView.HORIZONTAL, false)
50 |
51 | editText.setOnKeyListener(View.OnKeyListener { _, keyCode, event ->
52 | if (event?.action == KeyEvent.ACTION_DOWN && keyCode == KeyEvent.KEYCODE_ENTER) {
53 | viewModel.search(editText.text.toString())
54 | return@OnKeyListener true
55 | }
56 | false
57 | })
58 | search.setOnClickListener {
59 | viewModel.search(editText.text.toString())
60 | }
61 |
62 | adapter.clickListener = { movie ->
63 | clickedMovie = movie
64 | }
65 |
66 | viewModel = ViewModelProviders.of(this).get(SearchViewModel::class.java)
67 | viewModel.viewState.observe(this, Observer {
68 | adapter.items = it.movies
69 |
70 | if(clickedMovie == null && it.movies.isNotEmpty()){
71 | clickedMovie = it.movies[0]
72 | }
73 | })
74 | }
75 | }
--------------------------------------------------------------------------------
/flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "size" : "20x20",
5 | "idiom" : "iphone",
6 | "filename" : "Icon-App-20x20@2x.png",
7 | "scale" : "2x"
8 | },
9 | {
10 | "size" : "20x20",
11 | "idiom" : "iphone",
12 | "filename" : "Icon-App-20x20@3x.png",
13 | "scale" : "3x"
14 | },
15 | {
16 | "size" : "29x29",
17 | "idiom" : "iphone",
18 | "filename" : "Icon-App-29x29@1x.png",
19 | "scale" : "1x"
20 | },
21 | {
22 | "size" : "29x29",
23 | "idiom" : "iphone",
24 | "filename" : "Icon-App-29x29@2x.png",
25 | "scale" : "2x"
26 | },
27 | {
28 | "size" : "29x29",
29 | "idiom" : "iphone",
30 | "filename" : "Icon-App-29x29@3x.png",
31 | "scale" : "3x"
32 | },
33 | {
34 | "size" : "40x40",
35 | "idiom" : "iphone",
36 | "filename" : "Icon-App-40x40@2x.png",
37 | "scale" : "2x"
38 | },
39 | {
40 | "size" : "40x40",
41 | "idiom" : "iphone",
42 | "filename" : "Icon-App-40x40@3x.png",
43 | "scale" : "3x"
44 | },
45 | {
46 | "size" : "60x60",
47 | "idiom" : "iphone",
48 | "filename" : "Icon-App-60x60@2x.png",
49 | "scale" : "2x"
50 | },
51 | {
52 | "size" : "60x60",
53 | "idiom" : "iphone",
54 | "filename" : "Icon-App-60x60@3x.png",
55 | "scale" : "3x"
56 | },
57 | {
58 | "size" : "20x20",
59 | "idiom" : "ipad",
60 | "filename" : "Icon-App-20x20@1x.png",
61 | "scale" : "1x"
62 | },
63 | {
64 | "size" : "20x20",
65 | "idiom" : "ipad",
66 | "filename" : "Icon-App-20x20@2x.png",
67 | "scale" : "2x"
68 | },
69 | {
70 | "size" : "29x29",
71 | "idiom" : "ipad",
72 | "filename" : "Icon-App-29x29@1x.png",
73 | "scale" : "1x"
74 | },
75 | {
76 | "size" : "29x29",
77 | "idiom" : "ipad",
78 | "filename" : "Icon-App-29x29@2x.png",
79 | "scale" : "2x"
80 | },
81 | {
82 | "size" : "40x40",
83 | "idiom" : "ipad",
84 | "filename" : "Icon-App-40x40@1x.png",
85 | "scale" : "1x"
86 | },
87 | {
88 | "size" : "40x40",
89 | "idiom" : "ipad",
90 | "filename" : "Icon-App-40x40@2x.png",
91 | "scale" : "2x"
92 | },
93 | {
94 | "size" : "76x76",
95 | "idiom" : "ipad",
96 | "filename" : "Icon-App-76x76@1x.png",
97 | "scale" : "1x"
98 | },
99 | {
100 | "size" : "76x76",
101 | "idiom" : "ipad",
102 | "filename" : "Icon-App-76x76@2x.png",
103 | "scale" : "2x"
104 | },
105 | {
106 | "size" : "83.5x83.5",
107 | "idiom" : "ipad",
108 | "filename" : "Icon-App-83.5x83.5@2x.png",
109 | "scale" : "2x"
110 | },
111 | {
112 | "size" : "1024x1024",
113 | "idiom" : "ios-marketing",
114 | "filename" : "Icon-App-1024x1024@1x.png",
115 | "scale" : "1x"
116 | }
117 | ],
118 | "info" : {
119 | "version" : 1,
120 | "author" : "xcode"
121 | }
122 | }
123 |
--------------------------------------------------------------------------------
/flutter/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
31 |
32 |
33 |
34 |
40 |
41 |
42 |
43 |
44 |
45 |
56 |
58 |
64 |
65 |
66 |
67 |
68 |
69 |
75 |
77 |
83 |
84 |
85 |
86 |
88 |
89 |
92 |
93 |
94 |
--------------------------------------------------------------------------------
/android/app/src/main/res/layout/fragment_search.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
24 |
25 |
40 |
41 |
51 |
52 |
53 |
54 |
65 |
66 |
75 |
76 |
93 |
94 |
102 |
103 |
118 |
119 |
--------------------------------------------------------------------------------
/android/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Attempt to set APP_HOME
10 | # Resolve links: $0 may be a link
11 | PRG="$0"
12 | # Need this for relative symlinks.
13 | while [ -h "$PRG" ] ; do
14 | ls=`ls -ld "$PRG"`
15 | link=`expr "$ls" : '.*-> \(.*\)$'`
16 | if expr "$link" : '/.*' > /dev/null; then
17 | PRG="$link"
18 | else
19 | PRG=`dirname "$PRG"`"/$link"
20 | fi
21 | done
22 | SAVED="`pwd`"
23 | cd "`dirname \"$PRG\"`/" >/dev/null
24 | APP_HOME="`pwd -P`"
25 | cd "$SAVED" >/dev/null
26 |
27 | APP_NAME="Gradle"
28 | APP_BASE_NAME=`basename "$0"`
29 |
30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
31 | DEFAULT_JVM_OPTS=""
32 |
33 | # Use the maximum available, or set MAX_FD != -1 to use that value.
34 | MAX_FD="maximum"
35 |
36 | warn () {
37 | echo "$*"
38 | }
39 |
40 | die () {
41 | echo
42 | echo "$*"
43 | echo
44 | exit 1
45 | }
46 |
47 | # OS specific support (must be 'true' or 'false').
48 | cygwin=false
49 | msys=false
50 | darwin=false
51 | nonstop=false
52 | case "`uname`" in
53 | CYGWIN* )
54 | cygwin=true
55 | ;;
56 | Darwin* )
57 | darwin=true
58 | ;;
59 | MINGW* )
60 | msys=true
61 | ;;
62 | NONSTOP* )
63 | nonstop=true
64 | ;;
65 | esac
66 |
67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
68 |
69 | # Determine the Java command to use to start the JVM.
70 | if [ -n "$JAVA_HOME" ] ; then
71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
72 | # IBM's JDK on AIX uses strange locations for the executables
73 | JAVACMD="$JAVA_HOME/jre/sh/java"
74 | else
75 | JAVACMD="$JAVA_HOME/bin/java"
76 | fi
77 | if [ ! -x "$JAVACMD" ] ; then
78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
79 |
80 | Please set the JAVA_HOME variable in your environment to match the
81 | location of your Java installation."
82 | fi
83 | else
84 | JAVACMD="java"
85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
86 |
87 | Please set the JAVA_HOME variable in your environment to match the
88 | location of your Java installation."
89 | fi
90 |
91 | # Increase the maximum file descriptors if we can.
92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
93 | MAX_FD_LIMIT=`ulimit -H -n`
94 | if [ $? -eq 0 ] ; then
95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
96 | MAX_FD="$MAX_FD_LIMIT"
97 | fi
98 | ulimit -n $MAX_FD
99 | if [ $? -ne 0 ] ; then
100 | warn "Could not set maximum file descriptor limit: $MAX_FD"
101 | fi
102 | else
103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
104 | fi
105 | fi
106 |
107 | # For Darwin, add options to specify how the application appears in the dock
108 | if $darwin; then
109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
110 | fi
111 |
112 | # For Cygwin, switch paths to Windows format before running java
113 | if $cygwin ; then
114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
116 | JAVACMD=`cygpath --unix "$JAVACMD"`
117 |
118 | # We build the pattern for arguments to be converted via cygpath
119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
120 | SEP=""
121 | for dir in $ROOTDIRSRAW ; do
122 | ROOTDIRS="$ROOTDIRS$SEP$dir"
123 | SEP="|"
124 | done
125 | OURCYGPATTERN="(^($ROOTDIRS))"
126 | # Add a user-defined pattern to the cygpath arguments
127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
129 | fi
130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
131 | i=0
132 | for arg in "$@" ; do
133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
135 |
136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
138 | else
139 | eval `echo args$i`="\"$arg\""
140 | fi
141 | i=$((i+1))
142 | done
143 | case $i in
144 | (0) set -- ;;
145 | (1) set -- "$args0" ;;
146 | (2) set -- "$args0" "$args1" ;;
147 | (3) set -- "$args0" "$args1" "$args2" ;;
148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
154 | esac
155 | fi
156 |
157 | # Escape application args
158 | save () {
159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
160 | echo " "
161 | }
162 | APP_ARGS=$(save "$@")
163 |
164 | # Collect all arguments for the java command, following the shell quoting and substitution rules
165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
166 |
167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
169 | cd "$(dirname "$0")"
170 | fi
171 |
172 | exec "$JAVACMD" "$@"
173 |
--------------------------------------------------------------------------------
/android/app/src/main/res/drawable/ic_launcher_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
10 |
15 |
20 |
25 |
30 |
35 |
40 |
45 |
50 |
55 |
60 |
65 |
70 |
75 |
80 |
85 |
90 |
95 |
100 |
105 |
110 |
115 |
120 |
125 |
130 |
135 |
140 |
145 |
150 |
155 |
160 |
165 |
170 |
171 |
--------------------------------------------------------------------------------
/android/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
--------------------------------------------------------------------------------
/flutter/lib/search/SearchPage.dart:
--------------------------------------------------------------------------------
1 | import 'dart:ui';
2 | import 'package:flutter/material.dart';
3 | import 'package:mvvm_sample/omdb/OmdbRepository.dart';
4 | import 'package:mvvm_sample/omdb/models/Movie.dart';
5 | import 'package:mvvm_sample/search/SearchViewState.dart';
6 | import 'package:mvvm_sample/search/SearchViewModel.dart';
7 |
8 | const OmdbRepository repo = OmdbRepository();
9 |
10 | class SearchPage extends StatefulWidget {
11 | @override
12 | SearchPageState createState() {
13 | return new SearchPageState();
14 | }
15 | }
16 |
17 | class SearchPageState extends State {
18 | final viewModel = SearchViewModel(repo);
19 |
20 | Movie _currentMovie;
21 | var _editTextController = TextEditingController();
22 |
23 | void _searchMovie(String name) {
24 | viewModel.search(name);
25 | }
26 |
27 | void _changeCurrentMovie(Movie movie) {
28 | setState(() {
29 | _currentMovie = movie;
30 | });
31 | }
32 |
33 | Widget _currentMovieBackground() {
34 | if (_currentMovie != null) {
35 | return Column(mainAxisSize: MainAxisSize.max, children: [
36 | Expanded(
37 | child: Container(
38 | constraints: BoxConstraints.expand(),
39 | color: Colors.black,
40 | child: new Container(
41 | decoration: new BoxDecoration(
42 | image: new DecorationImage(
43 | image: new NetworkImage(_currentMovie.poster),
44 | fit: BoxFit.cover,
45 | ),
46 | ),
47 | child: new BackdropFilter(
48 | filter: new ImageFilter.blur(sigmaX: 4.0, sigmaY: 4.0),
49 | child: new Container(
50 | decoration: new BoxDecoration(
51 | color: Colors.black45.withAlpha(100)),
52 | ),
53 | ),
54 | ))),
55 | ]);
56 | } else {
57 | return Container(
58 | color: Colors.white,
59 | );
60 | }
61 | }
62 |
63 | Widget _currentMovieHeader() {
64 | if (_currentMovie != null) {
65 | return SingleChildScrollView(
66 | padding: EdgeInsets.symmetric(horizontal: 24, vertical: 48),
67 | child: Column(
68 | crossAxisAlignment: CrossAxisAlignment.start,
69 | children: [
70 | Text(
71 | _currentMovie.title.replaceAll(" ", "\n").toUpperCase(),
72 | style: TextStyle(
73 | shadows: [
74 | Shadow(
75 | offset: Offset(2.0, 2),
76 | blurRadius: 2.0,
77 | color: Colors.black87)
78 | ],
79 | color: Colors.white,
80 | fontSize: 44,
81 | fontFamily: 'Raleway',
82 | fontWeight: FontWeight.w700),
83 | ),
84 | Container(
85 | margin: EdgeInsets.symmetric(vertical: 16),
86 | height: 5,
87 | width: 30,
88 | color: Colors.red[200],
89 | ),
90 | Text(_currentMovie.type + " (" + _currentMovie.year + ")",
91 | style: TextStyle(
92 | shadows: [
93 | Shadow(
94 | offset: Offset(2.0, 2),
95 | blurRadius: 2.0,
96 | color: Colors.black87)
97 | ],
98 | fontFamily: 'Raleway',
99 | fontWeight: FontWeight.normal,
100 | color: Colors.white,
101 | fontSize: 20))
102 | ],
103 | ),
104 | );
105 | } else {
106 | return Container();
107 | }
108 | }
109 |
110 | Widget _buildInputText() {
111 | return Padding(
112 | padding: const EdgeInsets.symmetric(horizontal: 16),
113 | child: Material(
114 | elevation: 20.0,
115 | shadowColor: Colors.black,
116 | color: Colors.white,
117 | shape: RoundedRectangleBorder(
118 | borderRadius: BorderRadius.only(
119 | bottomLeft: Radius.circular(16),
120 | bottomRight: Radius.circular(16))),
121 | child: Padding(
122 | padding: const EdgeInsets.symmetric(horizontal: 18.0),
123 | child: Row(
124 | children: [
125 | Flexible(
126 | child: TextField(
127 | decoration:
128 | InputDecoration.collapsed(hintText: "Search movie"),
129 | onSubmitted: (text) {
130 | _searchMovie(_editTextController.text);
131 | },
132 | controller: _editTextController,
133 | ),
134 | ),
135 | IconButton(
136 | icon: Icon(Icons.search),
137 | onPressed: () {
138 | _searchMovie(_editTextController.text);
139 | },
140 | ),
141 | ],
142 | ),
143 | ),
144 | ),
145 | );
146 | }
147 |
148 | Widget _buildListView(SearchViewState viewmodel) {
149 | return Container(
150 | height: 250,
151 | margin: EdgeInsets.only(bottom: 10),
152 | child: ListView.builder(
153 | scrollDirection: Axis.horizontal,
154 | itemBuilder: (context, position) {
155 | var movie = viewmodel.movies[position];
156 | return Padding(
157 | padding:
158 | const EdgeInsets.only(left: 12.0, right: 12.0, bottom: 20),
159 | child: GestureDetector(
160 | onTap: () {
161 | _changeCurrentMovie(movie);
162 | },
163 | child: AspectRatio(
164 | aspectRatio: 10 / 16,
165 | child: Card(
166 | elevation: 10.0,
167 | clipBehavior: Clip.antiAlias,
168 | shape: RoundedRectangleBorder(
169 | borderRadius: BorderRadius.all(Radius.circular(20.0))),
170 | child: Image.network(
171 | movie.poster,
172 | fit: BoxFit.cover,
173 | ),
174 | ),
175 | ),
176 | ),
177 | );
178 | },
179 | itemCount: viewmodel.movies.length),
180 | );
181 | }
182 |
183 | @override
184 | Widget build(BuildContext context) {
185 | return StreamBuilder(
186 | stream: viewModel.viewState,
187 | builder: (context, snapshot) {
188 | if (snapshot.hasData) {
189 | var viewmodel = snapshot.data;
190 | if (_currentMovie == null) {
191 | _currentMovie =
192 | viewmodel.movies.length > 0 ? viewmodel.movies[0] : null;
193 | }
194 | return Stack(
195 | children: [
196 | _currentMovieBackground(),
197 | Column(
198 | crossAxisAlignment: CrossAxisAlignment.start,
199 | children: [
200 | _buildInputText(),
201 | _currentMovieHeader(),
202 | ],
203 | ),
204 | Align(
205 | alignment: FractionalOffset.bottomCenter,
206 | child: _buildListView(viewmodel),
207 | ),
208 | ],
209 | );
210 | }
211 | });
212 | }
213 | }
214 |
--------------------------------------------------------------------------------
/flutter/ios/Runner.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 46;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };
11 | 2D5378261FAA1A9400D5DBA9 /* flutter_assets in Resources */ = {isa = PBXBuildFile; fileRef = 2D5378251FAA1A9400D5DBA9 /* flutter_assets */; };
12 | 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
13 | 3B80C3941E831B6300D905FE /* App.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; };
14 | 3B80C3951E831B6300D905FE /* App.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
15 | 9705A1C61CF904A100538489 /* Flutter.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9740EEBA1CF902C7004384FC /* Flutter.framework */; };
16 | 9705A1C71CF904A300538489 /* Flutter.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 9740EEBA1CF902C7004384FC /* Flutter.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
17 | 9740EEB41CF90195004384FC /* Debug.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = 9740EEB21CF90195004384FC /* Debug.xcconfig */; };
18 | 978B8F6F1D3862AE00F588F7 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */; };
19 | 97C146F31CF9000F007C117D /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 97C146F21CF9000F007C117D /* main.m */; };
20 | 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
21 | 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
22 | 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; };
23 | /* End PBXBuildFile section */
24 |
25 | /* Begin PBXCopyFilesBuildPhase section */
26 | 9705A1C41CF9048500538489 /* Embed Frameworks */ = {
27 | isa = PBXCopyFilesBuildPhase;
28 | buildActionMask = 2147483647;
29 | dstPath = "";
30 | dstSubfolderSpec = 10;
31 | files = (
32 | 3B80C3951E831B6300D905FE /* App.framework in Embed Frameworks */,
33 | 9705A1C71CF904A300538489 /* Flutter.framework in Embed Frameworks */,
34 | );
35 | name = "Embed Frameworks";
36 | runOnlyForDeploymentPostprocessing = 0;
37 | };
38 | /* End PBXCopyFilesBuildPhase section */
39 |
40 | /* Begin PBXFileReference section */
41 | 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; };
42 | 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; };
43 | 2D5378251FAA1A9400D5DBA9 /* flutter_assets */ = {isa = PBXFileReference; lastKnownFileType = folder; name = flutter_assets; path = Flutter/flutter_assets; sourceTree = SOURCE_ROOT; };
44 | 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; };
45 | 3B80C3931E831B6300D905FE /* App.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = App.framework; path = Flutter/App.framework; sourceTree = ""; };
46 | 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; };
47 | 7AFFD8ED1D35381100E5BB4D /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; };
48 | 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; };
49 | 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; };
50 | 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; };
51 | 9740EEBA1CF902C7004384FC /* Flutter.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Flutter.framework; path = Flutter/Flutter.framework; sourceTree = ""; };
52 | 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; };
53 | 97C146F21CF9000F007C117D /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; };
54 | 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; };
55 | 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
56 | 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; };
57 | 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
58 | /* End PBXFileReference section */
59 |
60 | /* Begin PBXFrameworksBuildPhase section */
61 | 97C146EB1CF9000F007C117D /* Frameworks */ = {
62 | isa = PBXFrameworksBuildPhase;
63 | buildActionMask = 2147483647;
64 | files = (
65 | 9705A1C61CF904A100538489 /* Flutter.framework in Frameworks */,
66 | 3B80C3941E831B6300D905FE /* App.framework in Frameworks */,
67 | );
68 | runOnlyForDeploymentPostprocessing = 0;
69 | };
70 | /* End PBXFrameworksBuildPhase section */
71 |
72 | /* Begin PBXGroup section */
73 | 9740EEB11CF90186004384FC /* Flutter */ = {
74 | isa = PBXGroup;
75 | children = (
76 | 2D5378251FAA1A9400D5DBA9 /* flutter_assets */,
77 | 3B80C3931E831B6300D905FE /* App.framework */,
78 | 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */,
79 | 9740EEBA1CF902C7004384FC /* Flutter.framework */,
80 | 9740EEB21CF90195004384FC /* Debug.xcconfig */,
81 | 7AFA3C8E1D35360C0083082E /* Release.xcconfig */,
82 | 9740EEB31CF90195004384FC /* Generated.xcconfig */,
83 | );
84 | name = Flutter;
85 | sourceTree = "";
86 | };
87 | 97C146E51CF9000F007C117D = {
88 | isa = PBXGroup;
89 | children = (
90 | 9740EEB11CF90186004384FC /* Flutter */,
91 | 97C146F01CF9000F007C117D /* Runner */,
92 | 97C146EF1CF9000F007C117D /* Products */,
93 | CF3B75C9A7D2FA2A4C99F110 /* Frameworks */,
94 | );
95 | sourceTree = "";
96 | };
97 | 97C146EF1CF9000F007C117D /* Products */ = {
98 | isa = PBXGroup;
99 | children = (
100 | 97C146EE1CF9000F007C117D /* Runner.app */,
101 | );
102 | name = Products;
103 | sourceTree = "";
104 | };
105 | 97C146F01CF9000F007C117D /* Runner */ = {
106 | isa = PBXGroup;
107 | children = (
108 | 7AFFD8ED1D35381100E5BB4D /* AppDelegate.h */,
109 | 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */,
110 | 97C146FA1CF9000F007C117D /* Main.storyboard */,
111 | 97C146FD1CF9000F007C117D /* Assets.xcassets */,
112 | 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */,
113 | 97C147021CF9000F007C117D /* Info.plist */,
114 | 97C146F11CF9000F007C117D /* Supporting Files */,
115 | 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */,
116 | 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */,
117 | );
118 | path = Runner;
119 | sourceTree = "";
120 | };
121 | 97C146F11CF9000F007C117D /* Supporting Files */ = {
122 | isa = PBXGroup;
123 | children = (
124 | 97C146F21CF9000F007C117D /* main.m */,
125 | );
126 | name = "Supporting Files";
127 | sourceTree = "";
128 | };
129 | /* End PBXGroup section */
130 |
131 | /* Begin PBXNativeTarget section */
132 | 97C146ED1CF9000F007C117D /* Runner */ = {
133 | isa = PBXNativeTarget;
134 | buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
135 | buildPhases = (
136 | 9740EEB61CF901F6004384FC /* Run Script */,
137 | 97C146EA1CF9000F007C117D /* Sources */,
138 | 97C146EB1CF9000F007C117D /* Frameworks */,
139 | 97C146EC1CF9000F007C117D /* Resources */,
140 | 9705A1C41CF9048500538489 /* Embed Frameworks */,
141 | 3B06AD1E1E4923F5004D2608 /* Thin Binary */,
142 | );
143 | buildRules = (
144 | );
145 | dependencies = (
146 | );
147 | name = Runner;
148 | productName = Runner;
149 | productReference = 97C146EE1CF9000F007C117D /* Runner.app */;
150 | productType = "com.apple.product-type.application";
151 | };
152 | /* End PBXNativeTarget section */
153 |
154 | /* Begin PBXProject section */
155 | 97C146E61CF9000F007C117D /* Project object */ = {
156 | isa = PBXProject;
157 | attributes = {
158 | LastUpgradeCheck = 0910;
159 | ORGANIZATIONNAME = "The Chromium Authors";
160 | TargetAttributes = {
161 | 97C146ED1CF9000F007C117D = {
162 | CreatedOnToolsVersion = 7.3.1;
163 | };
164 | };
165 | };
166 | buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */;
167 | compatibilityVersion = "Xcode 3.2";
168 | developmentRegion = English;
169 | hasScannedForEncodings = 0;
170 | knownRegions = (
171 | en,
172 | Base,
173 | );
174 | mainGroup = 97C146E51CF9000F007C117D;
175 | productRefGroup = 97C146EF1CF9000F007C117D /* Products */;
176 | projectDirPath = "";
177 | projectRoot = "";
178 | targets = (
179 | 97C146ED1CF9000F007C117D /* Runner */,
180 | );
181 | };
182 | /* End PBXProject section */
183 |
184 | /* Begin PBXResourcesBuildPhase section */
185 | 97C146EC1CF9000F007C117D /* Resources */ = {
186 | isa = PBXResourcesBuildPhase;
187 | buildActionMask = 2147483647;
188 | files = (
189 | 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */,
190 | 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */,
191 | 9740EEB41CF90195004384FC /* Debug.xcconfig in Resources */,
192 | 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */,
193 | 2D5378261FAA1A9400D5DBA9 /* flutter_assets in Resources */,
194 | 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */,
195 | );
196 | runOnlyForDeploymentPostprocessing = 0;
197 | };
198 | /* End PBXResourcesBuildPhase section */
199 |
200 | /* Begin PBXShellScriptBuildPhase section */
201 | 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = {
202 | isa = PBXShellScriptBuildPhase;
203 | buildActionMask = 2147483647;
204 | files = (
205 | );
206 | inputPaths = (
207 | );
208 | name = "Thin Binary";
209 | outputPaths = (
210 | );
211 | runOnlyForDeploymentPostprocessing = 0;
212 | shellPath = /bin/sh;
213 | shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" thin";
214 | };
215 | 9740EEB61CF901F6004384FC /* Run Script */ = {
216 | isa = PBXShellScriptBuildPhase;
217 | buildActionMask = 2147483647;
218 | files = (
219 | );
220 | inputPaths = (
221 | );
222 | name = "Run Script";
223 | outputPaths = (
224 | );
225 | runOnlyForDeploymentPostprocessing = 0;
226 | shellPath = /bin/sh;
227 | shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build";
228 | };
229 | /* End PBXShellScriptBuildPhase section */
230 |
231 | /* Begin PBXSourcesBuildPhase section */
232 | 97C146EA1CF9000F007C117D /* Sources */ = {
233 | isa = PBXSourcesBuildPhase;
234 | buildActionMask = 2147483647;
235 | files = (
236 | 978B8F6F1D3862AE00F588F7 /* AppDelegate.m in Sources */,
237 | 97C146F31CF9000F007C117D /* main.m in Sources */,
238 | 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */,
239 | );
240 | runOnlyForDeploymentPostprocessing = 0;
241 | };
242 | /* End PBXSourcesBuildPhase section */
243 |
244 | /* Begin PBXVariantGroup section */
245 | 97C146FA1CF9000F007C117D /* Main.storyboard */ = {
246 | isa = PBXVariantGroup;
247 | children = (
248 | 97C146FB1CF9000F007C117D /* Base */,
249 | );
250 | name = Main.storyboard;
251 | sourceTree = "";
252 | };
253 | 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = {
254 | isa = PBXVariantGroup;
255 | children = (
256 | 97C147001CF9000F007C117D /* Base */,
257 | );
258 | name = LaunchScreen.storyboard;
259 | sourceTree = "";
260 | };
261 | /* End PBXVariantGroup section */
262 |
263 | /* Begin XCBuildConfiguration section */
264 | 249021D3217E4FDB00AE95B9 /* Profile */ = {
265 | isa = XCBuildConfiguration;
266 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
267 | buildSettings = {
268 | ALWAYS_SEARCH_USER_PATHS = NO;
269 | CLANG_ANALYZER_NONNULL = YES;
270 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
271 | CLANG_CXX_LIBRARY = "libc++";
272 | CLANG_ENABLE_MODULES = YES;
273 | CLANG_ENABLE_OBJC_ARC = YES;
274 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
275 | CLANG_WARN_BOOL_CONVERSION = YES;
276 | CLANG_WARN_COMMA = YES;
277 | CLANG_WARN_CONSTANT_CONVERSION = YES;
278 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
279 | CLANG_WARN_EMPTY_BODY = YES;
280 | CLANG_WARN_ENUM_CONVERSION = YES;
281 | CLANG_WARN_INFINITE_RECURSION = YES;
282 | CLANG_WARN_INT_CONVERSION = YES;
283 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
284 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
285 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
286 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
287 | CLANG_WARN_STRICT_PROTOTYPES = YES;
288 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
289 | CLANG_WARN_UNREACHABLE_CODE = YES;
290 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
291 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
292 | COPY_PHASE_STRIP = NO;
293 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
294 | ENABLE_NS_ASSERTIONS = NO;
295 | ENABLE_STRICT_OBJC_MSGSEND = YES;
296 | GCC_C_LANGUAGE_STANDARD = gnu99;
297 | GCC_NO_COMMON_BLOCKS = YES;
298 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
299 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
300 | GCC_WARN_UNDECLARED_SELECTOR = YES;
301 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
302 | GCC_WARN_UNUSED_FUNCTION = YES;
303 | GCC_WARN_UNUSED_VARIABLE = YES;
304 | IPHONEOS_DEPLOYMENT_TARGET = 8.0;
305 | MTL_ENABLE_DEBUG_INFO = NO;
306 | SDKROOT = iphoneos;
307 | TARGETED_DEVICE_FAMILY = "1,2";
308 | VALIDATE_PRODUCT = YES;
309 | };
310 | name = Profile;
311 | };
312 | 249021D4217E4FDB00AE95B9 /* Profile */ = {
313 | isa = XCBuildConfiguration;
314 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
315 | buildSettings = {
316 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
317 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
318 | DEVELOPMENT_TEAM = S8QB4VV633;
319 | ENABLE_BITCODE = NO;
320 | FRAMEWORK_SEARCH_PATHS = (
321 | "$(inherited)",
322 | "$(PROJECT_DIR)/Flutter",
323 | );
324 | INFOPLIST_FILE = Runner/Info.plist;
325 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
326 | LIBRARY_SEARCH_PATHS = (
327 | "$(inherited)",
328 | "$(PROJECT_DIR)/Flutter",
329 | );
330 | PRODUCT_BUNDLE_IDENTIFIER = com.example.mvvmSample;
331 | PRODUCT_NAME = "$(TARGET_NAME)";
332 | VERSIONING_SYSTEM = "apple-generic";
333 | };
334 | name = Profile;
335 | };
336 | 97C147031CF9000F007C117D /* Debug */ = {
337 | isa = XCBuildConfiguration;
338 | baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
339 | buildSettings = {
340 | ALWAYS_SEARCH_USER_PATHS = NO;
341 | CLANG_ANALYZER_NONNULL = YES;
342 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
343 | CLANG_CXX_LIBRARY = "libc++";
344 | CLANG_ENABLE_MODULES = YES;
345 | CLANG_ENABLE_OBJC_ARC = YES;
346 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
347 | CLANG_WARN_BOOL_CONVERSION = YES;
348 | CLANG_WARN_COMMA = YES;
349 | CLANG_WARN_CONSTANT_CONVERSION = YES;
350 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
351 | CLANG_WARN_EMPTY_BODY = YES;
352 | CLANG_WARN_ENUM_CONVERSION = YES;
353 | CLANG_WARN_INFINITE_RECURSION = YES;
354 | CLANG_WARN_INT_CONVERSION = YES;
355 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
356 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
357 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
358 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
359 | CLANG_WARN_STRICT_PROTOTYPES = YES;
360 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
361 | CLANG_WARN_UNREACHABLE_CODE = YES;
362 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
363 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
364 | COPY_PHASE_STRIP = NO;
365 | DEBUG_INFORMATION_FORMAT = dwarf;
366 | ENABLE_STRICT_OBJC_MSGSEND = YES;
367 | ENABLE_TESTABILITY = YES;
368 | GCC_C_LANGUAGE_STANDARD = gnu99;
369 | GCC_DYNAMIC_NO_PIC = NO;
370 | GCC_NO_COMMON_BLOCKS = YES;
371 | GCC_OPTIMIZATION_LEVEL = 0;
372 | GCC_PREPROCESSOR_DEFINITIONS = (
373 | "DEBUG=1",
374 | "$(inherited)",
375 | );
376 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
377 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
378 | GCC_WARN_UNDECLARED_SELECTOR = YES;
379 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
380 | GCC_WARN_UNUSED_FUNCTION = YES;
381 | GCC_WARN_UNUSED_VARIABLE = YES;
382 | IPHONEOS_DEPLOYMENT_TARGET = 8.0;
383 | MTL_ENABLE_DEBUG_INFO = YES;
384 | ONLY_ACTIVE_ARCH = YES;
385 | SDKROOT = iphoneos;
386 | TARGETED_DEVICE_FAMILY = "1,2";
387 | };
388 | name = Debug;
389 | };
390 | 97C147041CF9000F007C117D /* Release */ = {
391 | isa = XCBuildConfiguration;
392 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
393 | buildSettings = {
394 | ALWAYS_SEARCH_USER_PATHS = NO;
395 | CLANG_ANALYZER_NONNULL = YES;
396 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
397 | CLANG_CXX_LIBRARY = "libc++";
398 | CLANG_ENABLE_MODULES = YES;
399 | CLANG_ENABLE_OBJC_ARC = YES;
400 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
401 | CLANG_WARN_BOOL_CONVERSION = YES;
402 | CLANG_WARN_COMMA = YES;
403 | CLANG_WARN_CONSTANT_CONVERSION = YES;
404 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
405 | CLANG_WARN_EMPTY_BODY = YES;
406 | CLANG_WARN_ENUM_CONVERSION = YES;
407 | CLANG_WARN_INFINITE_RECURSION = YES;
408 | CLANG_WARN_INT_CONVERSION = YES;
409 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
410 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
411 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
412 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
413 | CLANG_WARN_STRICT_PROTOTYPES = YES;
414 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
415 | CLANG_WARN_UNREACHABLE_CODE = YES;
416 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
417 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
418 | COPY_PHASE_STRIP = NO;
419 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
420 | ENABLE_NS_ASSERTIONS = NO;
421 | ENABLE_STRICT_OBJC_MSGSEND = YES;
422 | GCC_C_LANGUAGE_STANDARD = gnu99;
423 | GCC_NO_COMMON_BLOCKS = YES;
424 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
425 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
426 | GCC_WARN_UNDECLARED_SELECTOR = YES;
427 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
428 | GCC_WARN_UNUSED_FUNCTION = YES;
429 | GCC_WARN_UNUSED_VARIABLE = YES;
430 | IPHONEOS_DEPLOYMENT_TARGET = 8.0;
431 | MTL_ENABLE_DEBUG_INFO = NO;
432 | SDKROOT = iphoneos;
433 | TARGETED_DEVICE_FAMILY = "1,2";
434 | VALIDATE_PRODUCT = YES;
435 | };
436 | name = Release;
437 | };
438 | 97C147061CF9000F007C117D /* Debug */ = {
439 | isa = XCBuildConfiguration;
440 | baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
441 | buildSettings = {
442 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
443 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
444 | ENABLE_BITCODE = NO;
445 | FRAMEWORK_SEARCH_PATHS = (
446 | "$(inherited)",
447 | "$(PROJECT_DIR)/Flutter",
448 | );
449 | INFOPLIST_FILE = Runner/Info.plist;
450 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
451 | LIBRARY_SEARCH_PATHS = (
452 | "$(inherited)",
453 | "$(PROJECT_DIR)/Flutter",
454 | );
455 | PRODUCT_BUNDLE_IDENTIFIER = com.example.mvvmSample;
456 | PRODUCT_NAME = "$(TARGET_NAME)";
457 | VERSIONING_SYSTEM = "apple-generic";
458 | };
459 | name = Debug;
460 | };
461 | 97C147071CF9000F007C117D /* Release */ = {
462 | isa = XCBuildConfiguration;
463 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
464 | buildSettings = {
465 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
466 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
467 | ENABLE_BITCODE = NO;
468 | FRAMEWORK_SEARCH_PATHS = (
469 | "$(inherited)",
470 | "$(PROJECT_DIR)/Flutter",
471 | );
472 | INFOPLIST_FILE = Runner/Info.plist;
473 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
474 | LIBRARY_SEARCH_PATHS = (
475 | "$(inherited)",
476 | "$(PROJECT_DIR)/Flutter",
477 | );
478 | PRODUCT_BUNDLE_IDENTIFIER = com.example.mvvmSample;
479 | PRODUCT_NAME = "$(TARGET_NAME)";
480 | VERSIONING_SYSTEM = "apple-generic";
481 | };
482 | name = Release;
483 | };
484 | /* End XCBuildConfiguration section */
485 |
486 | /* Begin XCConfigurationList section */
487 | 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = {
488 | isa = XCConfigurationList;
489 | buildConfigurations = (
490 | 97C147031CF9000F007C117D /* Debug */,
491 | 97C147041CF9000F007C117D /* Release */,
492 | 249021D3217E4FDB00AE95B9 /* Profile */,
493 | );
494 | defaultConfigurationIsVisible = 0;
495 | defaultConfigurationName = Release;
496 | };
497 | 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = {
498 | isa = XCConfigurationList;
499 | buildConfigurations = (
500 | 97C147061CF9000F007C117D /* Debug */,
501 | 97C147071CF9000F007C117D /* Release */,
502 | 249021D4217E4FDB00AE95B9 /* Profile */,
503 | );
504 | defaultConfigurationIsVisible = 0;
505 | defaultConfigurationName = Release;
506 | };
507 | /* End XCConfigurationList section */
508 | };
509 | rootObject = 97C146E61CF9000F007C117D /* Project object */;
510 | }
511 |
--------------------------------------------------------------------------------